diff --git a/.coveragerc b/.coveragerc index dd39c85..7936544 100644 --- a/.coveragerc +++ b/.coveragerc @@ -32,4 +32,5 @@ omit = */gapic/*.py */proto/*.py */core/*.py - */site-packages/*.py \ No newline at end of file + */site-packages/*.py + google/cloud/billing/budgets/__init__.py diff --git a/README.rst b/README.rst index e0abd4d..711838e 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,7 @@ Python Client for Cloud Billing Budget API ===================================================== -|beta| |pypi| |versions| +|beta| |pypi| |versions| `Cloud Billing Budget API`_: The Cloud Billing Budget API stores Cloud Billing budgets, which define a budget plan and the rules to execute as spend is tracked against that @@ -48,6 +48,15 @@ dependencies. .. _`virtualenv`: https://virtualenv.pypa.io/en/latest/ +Supported Python Versions +^^^^^^^^^^^^^^^^^^^^^^^^^ +Python >= 3.6 + +Deprecated Python Versions +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Python == 2.7. + +The last version of this library compatible with Python 2.7 is google-cloud-billing-budgets==0.4.0. Mac/Linux ^^^^^^^^^ diff --git a/UPGRADING.md b/UPGRADING.md new file mode 100644 index 0000000..74e38b1 --- /dev/null +++ b/UPGRADING.md @@ -0,0 +1,121 @@ +# 1.0.0 Migration Guide + +The 1.0 release of the `google-cloud-billing-budgets` client is a significant upgrade based on a [next-gen code generator](https://github.com/googleapis/gapic-generator-python), and includes substantial interface changes. Existing code written for earlier versions of this library will likely require updates to use this version. This document describes the changes that have been made, and what you need to do to update your usage. + +If you experience issues or have questions, please file an [issue](https://github.com/googleapis/python-billingbudgets/issues). + +## Supported Python Versions + +> **WARNING**: Breaking change + +The 1.0.0 release requires Python 3.6+. + + +## Namespace Change + +> **WARNING**: Breaking change + +The 1.0.0 release changes namespace from `google.cloud.billing_budgets` to `google.cloud.billing.budgets`. + +**Before:** +```py +from google.cloud import billing_budgets + +client = billing_budgets.BudgetServiceClient() +``` + + +**After:** +```py +from google.cloud.billing import budgets + +client = budgets.BudgetServiceClient() +``` + + +## Method Calls + +> **WARNING**: Breaking change + +Methods expect request objects. We provide a script that will convert most common use cases. + +* Install the library + +```py +python3 -m pip install google-cloud-billing-budgets +``` + +* The script `fixup_budgets_v1beta1_keywords.py` is shipped with the library. It expects +an input directory (with the code to convert) and an empty destination directory. + +```sh +$ fixup_budgets_v1beta1_keywords.py --input-directory .samples/ --output-directory samples/ +``` + +**Before:** +```py +budget = client.get_budget(name="billingAccounts/account/budgets/budget") +``` + + +**After:** +```py +budget = client.get_budget(request = {'name': "billingAccounts/account/budgets/budget"}) +``` + +### More Details + +In `google-cloud-billing-budgets<1.0.0`, parameters required by the API were positional parameters and optional parameters were keyword parameters. + +**Before:** +```py + def create_budget( + self, + parent, + budget, + retry=google.api_core.gapic_v1.method.DEFAULT, + timeout=google.api_core.gapic_v1.method.DEFAULT, + metadata=None, + ): +``` + +In the 1.0.0 release, all methods have a single positional parameter `request`. Method docstrings indicate whether a parameter is required or optional. + + +**After:** +```py + def create_budget( + self, + request: budget_service.CreateBudgetRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> budget_model.Budget: +``` + + +## Enums and Types + + +> **WARNING**: Breaking change + +The submodules `enums` and `types` have been removed. + +**Before:** +```py + +from google.cloud import billing_budgets + +filter = billing_budgets.enums.Filter.CreditTypesTreatment.INCLUDE_ALL_CREDITS +budget = billing_budgets.types.Budget() +``` + + +**After:** +```py +from google.cloud.billing import budgets + +filter = budgets.Filter.CreditTypesTreatment.INCLUDE_ALL_CREDITS +budget = budgets.Budget() +``` diff --git a/docs/UPGRADING.md b/docs/UPGRADING.md new file mode 120000 index 0000000..01097c8 --- /dev/null +++ b/docs/UPGRADING.md @@ -0,0 +1 @@ +../UPGRADING.md \ No newline at end of file diff --git a/docs/budgets_v1beta1/services.rst b/docs/budgets_v1beta1/services.rst new file mode 100644 index 0000000..91a4cb7 --- /dev/null +++ b/docs/budgets_v1beta1/services.rst @@ -0,0 +1,6 @@ +Services for Google Cloud Billing Budgets v1beta1 API +===================================================== + +.. automodule:: google.cloud.billing.budgets_v1beta1.services.budget_service + :members: + :inherited-members: diff --git a/docs/budgets_v1beta1/types.rst b/docs/budgets_v1beta1/types.rst new file mode 100644 index 0000000..78279ce --- /dev/null +++ b/docs/budgets_v1beta1/types.rst @@ -0,0 +1,5 @@ +Types for Google Cloud Billing Budgets v1beta1 API +================================================== + +.. automodule:: google.cloud.billing.budgets_v1beta1.types + :members: diff --git a/docs/gapic/v1beta1/api.rst b/docs/gapic/v1beta1/api.rst deleted file mode 100644 index b1f9f07..0000000 --- a/docs/gapic/v1beta1/api.rst +++ /dev/null @@ -1,6 +0,0 @@ -Client for Cloud Billing Budget API -=================================== - -.. automodule:: google.cloud.billing_budgets_v1beta1 - :members: - :inherited-members: \ No newline at end of file diff --git a/docs/gapic/v1beta1/types.rst b/docs/gapic/v1beta1/types.rst deleted file mode 100644 index d25d7a2..0000000 --- a/docs/gapic/v1beta1/types.rst +++ /dev/null @@ -1,5 +0,0 @@ -Types for Cloud Billing Budget API Client -========================================= - -.. automodule:: google.cloud.billing_budgets_v1beta1.types - :members: \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 7f667cc..6c090c3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -7,8 +7,18 @@ Api Reference .. toctree:: :maxdepth: 2 - gapic/v1beta1/api - gapic/v1beta1/types + budgets_v1beta1/services + budgets_v1beta1/types + +Migration Guide +--------------- + +See the guide below for instructions on migrating to the 2.x release of this library. + +.. toctree:: + :maxdepth: 2 + + UPGRADING Changelog --------- diff --git a/google/cloud/billing/budgets/__init__.py b/google/cloud/billing/budgets/__init__.py new file mode 100644 index 0000000..65880ac --- /dev/null +++ b/google/cloud/billing/budgets/__init__.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- + +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from google.cloud.billing.budgets_v1beta1.services.budget_service.async_client import ( + BudgetServiceAsyncClient, +) +from google.cloud.billing.budgets_v1beta1.services.budget_service.client import ( + BudgetServiceClient, +) +from google.cloud.billing.budgets_v1beta1.types.budget_model import AllUpdatesRule +from google.cloud.billing.budgets_v1beta1.types.budget_model import Budget +from google.cloud.billing.budgets_v1beta1.types.budget_model import BudgetAmount +from google.cloud.billing.budgets_v1beta1.types.budget_model import Filter +from google.cloud.billing.budgets_v1beta1.types.budget_model import LastPeriodAmount +from google.cloud.billing.budgets_v1beta1.types.budget_model import ThresholdRule +from google.cloud.billing.budgets_v1beta1.types.budget_service import ( + CreateBudgetRequest, +) +from google.cloud.billing.budgets_v1beta1.types.budget_service import ( + DeleteBudgetRequest, +) +from google.cloud.billing.budgets_v1beta1.types.budget_service import GetBudgetRequest +from google.cloud.billing.budgets_v1beta1.types.budget_service import ListBudgetsRequest +from google.cloud.billing.budgets_v1beta1.types.budget_service import ( + ListBudgetsResponse, +) +from google.cloud.billing.budgets_v1beta1.types.budget_service import ( + UpdateBudgetRequest, +) + +__all__ = ( + "AllUpdatesRule", + "Budget", + "BudgetAmount", + "BudgetServiceAsyncClient", + "BudgetServiceClient", + "CreateBudgetRequest", + "DeleteBudgetRequest", + "Filter", + "GetBudgetRequest", + "LastPeriodAmount", + "ListBudgetsRequest", + "ListBudgetsResponse", + "ThresholdRule", + "UpdateBudgetRequest", +) diff --git a/google/cloud/billing/budgets/py.typed b/google/cloud/billing/budgets/py.typed new file mode 100644 index 0000000..b067b19 --- /dev/null +++ b/google/cloud/billing/budgets/py.typed @@ -0,0 +1,2 @@ +# Marker file for PEP 561. +# The google-cloud-billing-budgets package uses inline types. diff --git a/google/cloud/billing/budgets_v1beta1/__init__.py b/google/cloud/billing/budgets_v1beta1/__init__.py new file mode 100644 index 0000000..cce38aa --- /dev/null +++ b/google/cloud/billing/budgets_v1beta1/__init__.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- + +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from .services.budget_service import BudgetServiceClient +from .types.budget_model import AllUpdatesRule +from .types.budget_model import Budget +from .types.budget_model import BudgetAmount +from .types.budget_model import Filter +from .types.budget_model import LastPeriodAmount +from .types.budget_model import ThresholdRule +from .types.budget_service import CreateBudgetRequest +from .types.budget_service import DeleteBudgetRequest +from .types.budget_service import GetBudgetRequest +from .types.budget_service import ListBudgetsRequest +from .types.budget_service import ListBudgetsResponse +from .types.budget_service import UpdateBudgetRequest + + +__all__ = ( + "AllUpdatesRule", + "Budget", + "BudgetAmount", + "CreateBudgetRequest", + "DeleteBudgetRequest", + "Filter", + "GetBudgetRequest", + "LastPeriodAmount", + "ListBudgetsRequest", + "ListBudgetsResponse", + "ThresholdRule", + "UpdateBudgetRequest", + "BudgetServiceClient", +) diff --git a/google/cloud/billing_budgets_v1beta1/proto/budget_model.proto b/google/cloud/billing/budgets_v1beta1/proto/budget_model.proto similarity index 100% rename from google/cloud/billing_budgets_v1beta1/proto/budget_model.proto rename to google/cloud/billing/budgets_v1beta1/proto/budget_model.proto diff --git a/google/cloud/billing_budgets_v1beta1/proto/budget_service.proto b/google/cloud/billing/budgets_v1beta1/proto/budget_service.proto similarity index 100% rename from google/cloud/billing_budgets_v1beta1/proto/budget_service.proto rename to google/cloud/billing/budgets_v1beta1/proto/budget_service.proto diff --git a/google/cloud/billing/budgets_v1beta1/py.typed b/google/cloud/billing/budgets_v1beta1/py.typed new file mode 100644 index 0000000..b067b19 --- /dev/null +++ b/google/cloud/billing/budgets_v1beta1/py.typed @@ -0,0 +1,2 @@ +# Marker file for PEP 561. +# The google-cloud-billing-budgets package uses inline types. diff --git a/google/cloud/__init__.py b/google/cloud/billing/budgets_v1beta1/services/__init__.py similarity index 71% rename from google/cloud/__init__.py rename to google/cloud/billing/budgets_v1beta1/services/__init__.py index 9a1b64a..42ffdf2 100644 --- a/google/cloud/__init__.py +++ b/google/cloud/billing/budgets_v1beta1/services/__init__.py @@ -1,24 +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 # -# https://www.apache.org/licenses/LICENSE-2.0 +# 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. - -try: - import pkg_resources - - pkg_resources.declare_namespace(__name__) -except ImportError: - import pkgutil - - __path__ = pkgutil.extend_path(__path__, __name__) +# diff --git a/google/__init__.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/__init__.py similarity index 71% rename from google/__init__.py rename to google/cloud/billing/budgets_v1beta1/services/budget_service/__init__.py index 9a1b64a..97d50ab 100644 --- a/google/__init__.py +++ b/google/cloud/billing/budgets_v1beta1/services/budget_service/__init__.py @@ -1,24 +1,24 @@ # -*- 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 # -# https://www.apache.org/licenses/LICENSE-2.0 +# 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. +# -try: - import pkg_resources - - pkg_resources.declare_namespace(__name__) -except ImportError: - import pkgutil +from .client import BudgetServiceClient +from .async_client import BudgetServiceAsyncClient - __path__ = pkgutil.extend_path(__path__, __name__) +__all__ = ( + "BudgetServiceClient", + "BudgetServiceAsyncClient", +) diff --git a/google/cloud/billing/budgets_v1beta1/services/budget_service/async_client.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/async_client.py new file mode 100644 index 0000000..c39f4f8 --- /dev/null +++ b/google/cloud/billing/budgets_v1beta1/services/budget_service/async_client.py @@ -0,0 +1,404 @@ +# -*- coding: utf-8 -*- + +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from collections import OrderedDict +import functools +import re +from typing import Dict, Sequence, Tuple, Type, Union +import pkg_resources + +import google.api_core.client_options as ClientOptions # type: ignore +from google.api_core import exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.billing.budgets_v1beta1.services.budget_service import pagers +from google.cloud.billing.budgets_v1beta1.types import budget_model +from google.cloud.billing.budgets_v1beta1.types import budget_service + +from .transports.base import BudgetServiceTransport +from .transports.grpc_asyncio import BudgetServiceGrpcAsyncIOTransport +from .client import BudgetServiceClient + + +class BudgetServiceAsyncClient: + """BudgetService stores Cloud Billing budgets, which define a + budget plan and rules to execute as we track spend against that + plan. + """ + + _client: BudgetServiceClient + + DEFAULT_ENDPOINT = BudgetServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = BudgetServiceClient.DEFAULT_MTLS_ENDPOINT + + budget_path = staticmethod(BudgetServiceClient.budget_path) + + from_service_account_file = BudgetServiceClient.from_service_account_file + from_service_account_json = from_service_account_file + + get_transport_class = functools.partial( + type(BudgetServiceClient).get_transport_class, type(BudgetServiceClient) + ) + + def __init__( + self, + *, + credentials: credentials.Credentials = None, + transport: Union[str, BudgetServiceTransport] = "grpc_asyncio", + client_options: ClientOptions = None, + ) -> None: + """Instantiate the budget service client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Union[str, ~.BudgetServiceTransport]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (ClientOptions): Custom options for the client. It + won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS + environment variable can also be used to override the endpoint: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint, this is the default value for + the environment variable) and "auto" (auto switch to the default + mTLS endpoint if client SSL credentials is present). However, + the ``api_endpoint`` property takes precedence if provided. + (2) The ``client_cert_source`` property is used to provide client + SSL credentials for mutual TLS transport. If not provided, the + default SSL credentials will be used if present. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + """ + + self._client = BudgetServiceClient( + credentials=credentials, transport=transport, client_options=client_options, + ) + + async def create_budget( + self, + request: budget_service.CreateBudgetRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> budget_model.Budget: + r"""Creates a new budget. See + Quotas + and limits for more information on the limits of the + number of budgets you can create. + + Args: + request (:class:`~.budget_service.CreateBudgetRequest`): + The request object. Request for CreateBudget + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.budget_model.Budget: + A budget is a plan that describes + what you expect to spend on Cloud + projects, plus the rules to execute as + spend is tracked against that plan, (for + example, send an alert when 90% of the + target spend is met). Currently all + plans are monthly budgets so the usage + period(s) tracked are implied (calendar + months of usage back-to-back). + + """ + # Create or coerce a protobuf request object. + + request = budget_service.CreateBudgetRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.create_budget, + default_timeout=None, + client_info=_client_info, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Done; return the response. + return response + + async def update_budget( + self, + request: budget_service.UpdateBudgetRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> budget_model.Budget: + r"""Updates a budget and returns the updated budget. + WARNING: There are some fields exposed on the Google + Cloud Console that aren't available on this API. Budget + fields that are not exposed in this API will not be + changed by this method. + + Args: + request (:class:`~.budget_service.UpdateBudgetRequest`): + The request object. Request for UpdateBudget + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.budget_model.Budget: + A budget is a plan that describes + what you expect to spend on Cloud + projects, plus the rules to execute as + spend is tracked against that plan, (for + example, send an alert when 90% of the + target spend is met). Currently all + plans are monthly budgets so the usage + period(s) tracked are implied (calendar + months of usage back-to-back). + + """ + # Create or coerce a protobuf request object. + + request = budget_service.UpdateBudgetRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.update_budget, + default_timeout=None, + client_info=_client_info, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("budget.name", request.budget.name),) + ), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Done; return the response. + return response + + async def get_budget( + self, + request: budget_service.GetBudgetRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> budget_model.Budget: + r"""Returns a budget. + WARNING: There are some fields exposed on the Google + Cloud Console that aren't available on this API. When + reading from the API, you will not see these fields in + the return value, though they may have been set in the + Cloud Console. + + Args: + request (:class:`~.budget_service.GetBudgetRequest`): + The request object. Request for GetBudget + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.budget_model.Budget: + A budget is a plan that describes + what you expect to spend on Cloud + projects, plus the rules to execute as + spend is tracked against that plan, (for + example, send an alert when 90% of the + target spend is met). Currently all + plans are monthly budgets so the usage + period(s) tracked are implied (calendar + months of usage back-to-back). + + """ + # Create or coerce a protobuf request object. + + request = budget_service.GetBudgetRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.get_budget, + default_timeout=None, + client_info=_client_info, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Done; return the response. + return response + + async def list_budgets( + self, + request: budget_service.ListBudgetsRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> pagers.ListBudgetsAsyncPager: + r"""Returns a list of budgets for a billing account. + WARNING: There are some fields exposed on the Google + Cloud Console that aren't available on this API. When + reading from the API, you will not see these fields in + the return value, though they may have been set in the + Cloud Console. + + Args: + request (:class:`~.budget_service.ListBudgetsRequest`): + The request object. Request for ListBudgets + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.pagers.ListBudgetsAsyncPager: + Response for ListBudgets + Iterating over this object will yield + results and resolve additional pages + automatically. + + """ + # Create or coerce a protobuf request object. + + request = budget_service.ListBudgetsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.list_budgets, + default_timeout=None, + client_info=_client_info, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # This method is paged; wrap the response in a pager, which provides + # an `__aiter__` convenience method. + response = pagers.ListBudgetsAsyncPager( + method=rpc, request=request, response=response, metadata=metadata, + ) + + # Done; return the response. + return response + + async def delete_budget( + self, + request: budget_service.DeleteBudgetRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> None: + r"""Deletes a budget. Returns successfully if already + deleted. + + Args: + request (:class:`~.budget_service.DeleteBudgetRequest`): + The request object. Request for DeleteBudget + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + # Create or coerce a protobuf request object. + + request = budget_service.DeleteBudgetRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.delete_budget, + default_timeout=None, + client_info=_client_info, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + await rpc( + request, retry=retry, timeout=timeout, metadata=metadata, + ) + + +try: + _client_info = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-cloud-billing-budgets", + ).version, + ) +except pkg_resources.DistributionNotFound: + _client_info = gapic_v1.client_info.ClientInfo() + + +__all__ = ("BudgetServiceAsyncClient",) diff --git a/google/cloud/billing/budgets_v1beta1/services/budget_service/client.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/client.py new file mode 100644 index 0000000..8db8e78 --- /dev/null +++ b/google/cloud/billing/budgets_v1beta1/services/budget_service/client.py @@ -0,0 +1,538 @@ +# -*- coding: utf-8 -*- + +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from collections import OrderedDict +import os +import re +from typing import Callable, Dict, Sequence, Tuple, Type, Union +import pkg_resources + +import google.api_core.client_options as ClientOptions # type: ignore +from google.api_core import exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.billing.budgets_v1beta1.services.budget_service import pagers +from google.cloud.billing.budgets_v1beta1.types import budget_model +from google.cloud.billing.budgets_v1beta1.types import budget_service + +from .transports.base import BudgetServiceTransport +from .transports.grpc import BudgetServiceGrpcTransport +from .transports.grpc_asyncio import BudgetServiceGrpcAsyncIOTransport + + +class BudgetServiceClientMeta(type): + """Metaclass for the BudgetService client. + + This provides class-level methods for building and retrieving + support objects (e.g. transport) without polluting the client instance + objects. + """ + + _transport_registry = OrderedDict() # type: Dict[str, Type[BudgetServiceTransport]] + _transport_registry["grpc"] = BudgetServiceGrpcTransport + _transport_registry["grpc_asyncio"] = BudgetServiceGrpcAsyncIOTransport + + def get_transport_class(cls, label: str = None,) -> Type[BudgetServiceTransport]: + """Return an appropriate transport class. + + Args: + label: The name of the desired transport. If none is + provided, then the first transport in the registry is used. + + Returns: + The transport class to use. + """ + # If a specific transport is requested, return that one. + if label: + return cls._transport_registry[label] + + # No transport is requested; return the default (that is, the first one + # in the dictionary). + return next(iter(cls._transport_registry.values())) + + +class BudgetServiceClient(metaclass=BudgetServiceClientMeta): + """BudgetService stores Cloud Billing budgets, which define a + budget plan and rules to execute as we track spend against that + plan. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Convert api endpoint to mTLS endpoint. + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + DEFAULT_ENDPOINT = "billingbudgets.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + {@api.name}: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_file(filename) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + from_service_account_json = from_service_account_file + + @staticmethod + def budget_path(billing_account: str, budget: str,) -> str: + """Return a fully-qualified budget string.""" + return "billingAccounts/{billing_account}/budgets/{budget}".format( + billing_account=billing_account, budget=budget, + ) + + @staticmethod + def parse_budget_path(path: str) -> Dict[str, str]: + """Parse a budget path into its component segments.""" + m = re.match( + r"^billingAccounts/(?P.+?)/budgets/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + def __init__( + self, + *, + credentials: credentials.Credentials = None, + transport: Union[str, BudgetServiceTransport] = None, + client_options: ClientOptions = None, + ) -> None: + """Instantiate the budget service client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Union[str, ~.BudgetServiceTransport]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (ClientOptions): Custom options for the client. It + won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS + environment variable can also be used to override the endpoint: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint, this is the default value for + the environment variable) and "auto" (auto switch to the default + mTLS endpoint if client SSL credentials is present). However, + the ``api_endpoint`` property takes precedence if provided. + (2) The ``client_cert_source`` property is used to provide client + SSL credentials for mutual TLS transport. If not provided, the + default SSL credentials will be used if present. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + """ + if isinstance(client_options, dict): + client_options = ClientOptions.from_dict(client_options) + if client_options is None: + client_options = ClientOptions.ClientOptions() + + if client_options.api_endpoint is None: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS", "never") + if use_mtls_env == "never": + client_options.api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + client_options.api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + has_client_cert_source = ( + client_options.client_cert_source is not None + or mtls.has_default_client_cert_source() + ) + client_options.api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if has_client_cert_source + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS value. Accepted values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, BudgetServiceTransport): + # transport is a BudgetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, " + "provide its scopes directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=client_options.api_endpoint, + scopes=client_options.scopes, + api_mtls_endpoint=client_options.api_endpoint, + client_cert_source=client_options.client_cert_source, + ) + + def create_budget( + self, + request: budget_service.CreateBudgetRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> budget_model.Budget: + r"""Creates a new budget. See + Quotas + and limits for more information on the limits of the + number of budgets you can create. + + Args: + request (:class:`~.budget_service.CreateBudgetRequest`): + The request object. Request for CreateBudget + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.budget_model.Budget: + A budget is a plan that describes + what you expect to spend on Cloud + projects, plus the rules to execute as + spend is tracked against that plan, (for + example, send an alert when 90% of the + target spend is met). Currently all + plans are monthly budgets so the usage + period(s) tracked are implied (calendar + months of usage back-to-back). + + """ + # Create or coerce a protobuf request object. + + request = budget_service.CreateBudgetRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.create_budget, + default_timeout=None, + client_info=_client_info, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Done; return the response. + return response + + def update_budget( + self, + request: budget_service.UpdateBudgetRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> budget_model.Budget: + r"""Updates a budget and returns the updated budget. + WARNING: There are some fields exposed on the Google + Cloud Console that aren't available on this API. Budget + fields that are not exposed in this API will not be + changed by this method. + + Args: + request (:class:`~.budget_service.UpdateBudgetRequest`): + The request object. Request for UpdateBudget + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.budget_model.Budget: + A budget is a plan that describes + what you expect to spend on Cloud + projects, plus the rules to execute as + spend is tracked against that plan, (for + example, send an alert when 90% of the + target spend is met). Currently all + plans are monthly budgets so the usage + period(s) tracked are implied (calendar + months of usage back-to-back). + + """ + # Create or coerce a protobuf request object. + + request = budget_service.UpdateBudgetRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.update_budget, + default_timeout=None, + client_info=_client_info, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("budget.name", request.budget.name),) + ), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Done; return the response. + return response + + def get_budget( + self, + request: budget_service.GetBudgetRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> budget_model.Budget: + r"""Returns a budget. + WARNING: There are some fields exposed on the Google + Cloud Console that aren't available on this API. When + reading from the API, you will not see these fields in + the return value, though they may have been set in the + Cloud Console. + + Args: + request (:class:`~.budget_service.GetBudgetRequest`): + The request object. Request for GetBudget + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.budget_model.Budget: + A budget is a plan that describes + what you expect to spend on Cloud + projects, plus the rules to execute as + spend is tracked against that plan, (for + example, send an alert when 90% of the + target spend is met). Currently all + plans are monthly budgets so the usage + period(s) tracked are implied (calendar + months of usage back-to-back). + + """ + # Create or coerce a protobuf request object. + + request = budget_service.GetBudgetRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.get_budget, default_timeout=None, client_info=_client_info, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Done; return the response. + return response + + def list_budgets( + self, + request: budget_service.ListBudgetsRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> pagers.ListBudgetsPager: + r"""Returns a list of budgets for a billing account. + WARNING: There are some fields exposed on the Google + Cloud Console that aren't available on this API. When + reading from the API, you will not see these fields in + the return value, though they may have been set in the + Cloud Console. + + Args: + request (:class:`~.budget_service.ListBudgetsRequest`): + The request object. Request for ListBudgets + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.pagers.ListBudgetsPager: + Response for ListBudgets + Iterating over this object will yield + results and resolve additional pages + automatically. + + """ + # Create or coerce a protobuf request object. + + request = budget_service.ListBudgetsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.list_budgets, + default_timeout=None, + client_info=_client_info, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # This method is paged; wrap the response in a pager, which provides + # an `__iter__` convenience method. + response = pagers.ListBudgetsPager( + method=rpc, request=request, response=response, metadata=metadata, + ) + + # Done; return the response. + return response + + def delete_budget( + self, + request: budget_service.DeleteBudgetRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> None: + r"""Deletes a budget. Returns successfully if already + deleted. + + Args: + request (:class:`~.budget_service.DeleteBudgetRequest`): + The request object. Request for DeleteBudget + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + # Create or coerce a protobuf request object. + + request = budget_service.DeleteBudgetRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.delete_budget, + default_timeout=None, + client_info=_client_info, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + rpc( + request, retry=retry, timeout=timeout, metadata=metadata, + ) + + +try: + _client_info = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-cloud-billing-budgets", + ).version, + ) +except pkg_resources.DistributionNotFound: + _client_info = gapic_v1.client_info.ClientInfo() + + +__all__ = ("BudgetServiceClient",) diff --git a/google/cloud/billing/budgets_v1beta1/services/budget_service/pagers.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/pagers.py new file mode 100644 index 0000000..b9456d3 --- /dev/null +++ b/google/cloud/billing/budgets_v1beta1/services/budget_service/pagers.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- + +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from typing import Any, AsyncIterable, Awaitable, Callable, Iterable, Sequence, Tuple + +from google.cloud.billing.budgets_v1beta1.types import budget_model +from google.cloud.billing.budgets_v1beta1.types import budget_service + + +class ListBudgetsPager: + """A pager for iterating through ``list_budgets`` requests. + + This class thinly wraps an initial + :class:`~.budget_service.ListBudgetsResponse` object, and + provides an ``__iter__`` method to iterate through its + ``budgets`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``ListBudgets`` requests and continue to iterate + through the ``budgets`` field on the + corresponding responses. + + All the usual :class:`~.budget_service.ListBudgetsResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[..., budget_service.ListBudgetsResponse], + request: budget_service.ListBudgetsRequest, + response: budget_service.ListBudgetsResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (:class:`~.budget_service.ListBudgetsRequest`): + The initial request object. + response (:class:`~.budget_service.ListBudgetsResponse`): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = budget_service.ListBudgetsRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages(self) -> Iterable[budget_service.ListBudgetsResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = self._method(self._request, metadata=self._metadata) + yield self._response + + def __iter__(self) -> Iterable[budget_model.Budget]: + for page in self.pages: + yield from page.budgets + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListBudgetsAsyncPager: + """A pager for iterating through ``list_budgets`` requests. + + This class thinly wraps an initial + :class:`~.budget_service.ListBudgetsResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``budgets`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``ListBudgets`` requests and continue to iterate + through the ``budgets`` field on the + corresponding responses. + + All the usual :class:`~.budget_service.ListBudgetsResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[..., Awaitable[budget_service.ListBudgetsResponse]], + request: budget_service.ListBudgetsRequest, + response: budget_service.ListBudgetsResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (:class:`~.budget_service.ListBudgetsRequest`): + The initial request object. + response (:class:`~.budget_service.ListBudgetsResponse`): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = budget_service.ListBudgetsRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + async def pages(self) -> AsyncIterable[budget_service.ListBudgetsResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = await self._method(self._request, metadata=self._metadata) + yield self._response + + def __aiter__(self) -> AsyncIterable[budget_model.Budget]: + async def async_generator(): + async for page in self.pages: + for response in page.budgets: + yield response + + return async_generator() + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) diff --git a/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/__init__.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/__init__.py new file mode 100644 index 0000000..8f54d9e --- /dev/null +++ b/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- + +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from collections import OrderedDict +from typing import Dict, Type + +from .base import BudgetServiceTransport +from .grpc import BudgetServiceGrpcTransport +from .grpc_asyncio import BudgetServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = OrderedDict() # type: Dict[str, Type[BudgetServiceTransport]] +_transport_registry["grpc"] = BudgetServiceGrpcTransport +_transport_registry["grpc_asyncio"] = BudgetServiceGrpcAsyncIOTransport + + +__all__ = ( + "BudgetServiceTransport", + "BudgetServiceGrpcTransport", + "BudgetServiceGrpcAsyncIOTransport", +) diff --git a/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/base.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/base.py new file mode 100644 index 0000000..7927b36 --- /dev/null +++ b/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/base.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- + +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import abc +import typing + +from google import auth +from google.api_core import exceptions # type: ignore +from google.auth import credentials # type: ignore + +from google.cloud.billing.budgets_v1beta1.types import budget_model +from google.cloud.billing.budgets_v1beta1.types import budget_service +from google.protobuf import empty_pb2 as empty # type: ignore + + +class BudgetServiceTransport(abc.ABC): + """Abstract transport class for BudgetService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + + def __init__( + self, + *, + host: str = "billingbudgets.googleapis.com", + credentials: credentials.Credentials = None, + credentials_file: typing.Optional[str] = None, + scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scope (Optional[Sequence[str]]): A list of scopes. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = auth.load_credentials_from_file( + credentials_file, scopes=scopes + ) + elif credentials is None: + credentials, _ = auth.default(scopes=scopes) + + # Save the credentials. + self._credentials = credentials + + @property + def create_budget( + self, + ) -> typing.Callable[ + [budget_service.CreateBudgetRequest], + typing.Union[budget_model.Budget, typing.Awaitable[budget_model.Budget]], + ]: + raise NotImplementedError() + + @property + def update_budget( + self, + ) -> typing.Callable[ + [budget_service.UpdateBudgetRequest], + typing.Union[budget_model.Budget, typing.Awaitable[budget_model.Budget]], + ]: + raise NotImplementedError() + + @property + def get_budget( + self, + ) -> typing.Callable[ + [budget_service.GetBudgetRequest], + typing.Union[budget_model.Budget, typing.Awaitable[budget_model.Budget]], + ]: + raise NotImplementedError() + + @property + def list_budgets( + self, + ) -> typing.Callable[ + [budget_service.ListBudgetsRequest], + typing.Union[ + budget_service.ListBudgetsResponse, + typing.Awaitable[budget_service.ListBudgetsResponse], + ], + ]: + raise NotImplementedError() + + @property + def delete_budget( + self, + ) -> typing.Callable[ + [budget_service.DeleteBudgetRequest], + typing.Union[empty.Empty, typing.Awaitable[empty.Empty]], + ]: + raise NotImplementedError() + + +__all__ = ("BudgetServiceTransport",) diff --git a/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/grpc.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/grpc.py new file mode 100644 index 0000000..84e78cc --- /dev/null +++ b/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/grpc.py @@ -0,0 +1,350 @@ +# -*- coding: utf-8 -*- + +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from typing import Callable, Dict, Optional, Sequence, Tuple + +from google.api_core import grpc_helpers # type: ignore +from google import auth # type: ignore +from google.auth import credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore + + +import grpc # type: ignore + +from google.cloud.billing.budgets_v1beta1.types import budget_model +from google.cloud.billing.budgets_v1beta1.types import budget_service +from google.protobuf import empty_pb2 as empty # type: ignore + +from .base import BudgetServiceTransport + + +class BudgetServiceGrpcTransport(BudgetServiceTransport): + """gRPC backend transport for BudgetService. + + BudgetService stores Cloud Billing budgets, which define a + budget plan and rules to execute as we track spend against that + plan. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _stubs: Dict[str, Callable] + + def __init__( + self, + *, + host: str = "billingbudgets.googleapis.com", + credentials: credentials.Credentials = None, + credentials_file: str = None, + scopes: Sequence[str] = None, + channel: grpc.Channel = None, + api_mtls_endpoint: str = None, + client_cert_source: Callable[[], Tuple[bytes, bytes]] = None + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If + provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or applicatin default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A + callback to provide client SSL certificate bytes and private key + bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` + is None. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + if channel: + # Sanity check: Ensure that channel and credentials are not both + # provided. + credentials = False + + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + 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) + + # 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, + ) + + # Run the base constructor. + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes or self.AUTH_SCOPES, + ) + + self._stubs = {} # type: Dict[str, Callable] + + @classmethod + def create_channel( + cls, + host: str = "billingbudgets.googleapis.com", + credentials: credentials.Credentials = None, + credentials_file: str = None, + scopes: Optional[Sequence[str]] = None, + **kwargs + ) -> grpc.Channel: + """Create and return a gRPC channel object. + Args: + address (Optionsl[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + scopes = scopes or cls.AUTH_SCOPES + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + **kwargs + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Create the channel designed to connect to this service. + + This property caches on the instance; repeated calls return + the same channel. + """ + # Sanity check: Only create a new channel if we do not already + # have one. + if not hasattr(self, "_grpc_channel"): + self._grpc_channel = self.create_channel( + self._host, credentials=self._credentials, + ) + + # Return the channel from cache. + return self._grpc_channel + + @property + def create_budget( + self, + ) -> Callable[[budget_service.CreateBudgetRequest], budget_model.Budget]: + r"""Return a callable for the create budget method over gRPC. + + Creates a new budget. See + Quotas + and limits for more information on the limits of the + number of budgets you can create. + + Returns: + Callable[[~.CreateBudgetRequest], + ~.Budget]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_budget" not in self._stubs: + self._stubs["create_budget"] = self.grpc_channel.unary_unary( + "/google.cloud.billing.budgets.v1beta1.BudgetService/CreateBudget", + request_serializer=budget_service.CreateBudgetRequest.serialize, + response_deserializer=budget_model.Budget.deserialize, + ) + return self._stubs["create_budget"] + + @property + def update_budget( + self, + ) -> Callable[[budget_service.UpdateBudgetRequest], budget_model.Budget]: + r"""Return a callable for the update budget method over gRPC. + + Updates a budget and returns the updated budget. + WARNING: There are some fields exposed on the Google + Cloud Console that aren't available on this API. Budget + fields that are not exposed in this API will not be + changed by this method. + + Returns: + Callable[[~.UpdateBudgetRequest], + ~.Budget]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_budget" not in self._stubs: + self._stubs["update_budget"] = self.grpc_channel.unary_unary( + "/google.cloud.billing.budgets.v1beta1.BudgetService/UpdateBudget", + request_serializer=budget_service.UpdateBudgetRequest.serialize, + response_deserializer=budget_model.Budget.deserialize, + ) + return self._stubs["update_budget"] + + @property + def get_budget( + self, + ) -> Callable[[budget_service.GetBudgetRequest], budget_model.Budget]: + r"""Return a callable for the get budget method over gRPC. + + Returns a budget. + WARNING: There are some fields exposed on the Google + Cloud Console that aren't available on this API. When + reading from the API, you will not see these fields in + the return value, though they may have been set in the + Cloud Console. + + Returns: + Callable[[~.GetBudgetRequest], + ~.Budget]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_budget" not in self._stubs: + self._stubs["get_budget"] = self.grpc_channel.unary_unary( + "/google.cloud.billing.budgets.v1beta1.BudgetService/GetBudget", + request_serializer=budget_service.GetBudgetRequest.serialize, + response_deserializer=budget_model.Budget.deserialize, + ) + return self._stubs["get_budget"] + + @property + def list_budgets( + self, + ) -> Callable[ + [budget_service.ListBudgetsRequest], budget_service.ListBudgetsResponse + ]: + r"""Return a callable for the list budgets method over gRPC. + + Returns a list of budgets for a billing account. + WARNING: There are some fields exposed on the Google + Cloud Console that aren't available on this API. When + reading from the API, you will not see these fields in + the return value, though they may have been set in the + Cloud Console. + + Returns: + Callable[[~.ListBudgetsRequest], + ~.ListBudgetsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_budgets" not in self._stubs: + self._stubs["list_budgets"] = self.grpc_channel.unary_unary( + "/google.cloud.billing.budgets.v1beta1.BudgetService/ListBudgets", + request_serializer=budget_service.ListBudgetsRequest.serialize, + response_deserializer=budget_service.ListBudgetsResponse.deserialize, + ) + return self._stubs["list_budgets"] + + @property + def delete_budget( + self, + ) -> Callable[[budget_service.DeleteBudgetRequest], empty.Empty]: + r"""Return a callable for the delete budget method over gRPC. + + Deletes a budget. Returns successfully if already + deleted. + + Returns: + Callable[[~.DeleteBudgetRequest], + ~.Empty]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "delete_budget" not in self._stubs: + self._stubs["delete_budget"] = self.grpc_channel.unary_unary( + "/google.cloud.billing.budgets.v1beta1.BudgetService/DeleteBudget", + request_serializer=budget_service.DeleteBudgetRequest.serialize, + response_deserializer=empty.Empty.FromString, + ) + return self._stubs["delete_budget"] + + +__all__ = ("BudgetServiceGrpcTransport",) diff --git a/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/grpc_asyncio.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/grpc_asyncio.py new file mode 100644 index 0000000..602a735 --- /dev/null +++ b/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/grpc_asyncio.py @@ -0,0 +1,346 @@ +# -*- coding: utf-8 -*- + +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple + +from google.api_core import grpc_helpers_async # type: ignore +from google.auth import credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore + +import grpc # type: ignore +from grpc.experimental import aio # type: ignore + +from google.cloud.billing.budgets_v1beta1.types import budget_model +from google.cloud.billing.budgets_v1beta1.types import budget_service +from google.protobuf import empty_pb2 as empty # type: ignore + +from .base import BudgetServiceTransport +from .grpc import BudgetServiceGrpcTransport + + +class BudgetServiceGrpcAsyncIOTransport(BudgetServiceTransport): + """gRPC AsyncIO backend transport for BudgetService. + + BudgetService stores Cloud Billing budgets, which define a + budget plan and rules to execute as we track spend against that + plan. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _grpc_channel: aio.Channel + _stubs: Dict[str, Callable] = {} + + @classmethod + def create_channel( + cls, + host: str = "billingbudgets.googleapis.com", + credentials: credentials.Credentials = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + **kwargs + ) -> aio.Channel: + """Create and return a gRPC AsyncIO channel object. + Args: + address (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + aio.Channel: A gRPC AsyncIO channel object. + """ + scopes = scopes or cls.AUTH_SCOPES + return grpc_helpers_async.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + **kwargs + ) + + def __init__( + self, + *, + host: str = "billingbudgets.googleapis.com", + credentials: credentials.Credentials = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: aio.Channel = None, + api_mtls_endpoint: str = None, + client_cert_source: Callable[[], Tuple[bytes, bytes]] = None + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + channel (Optional[aio.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If + provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or applicatin default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A + callback to provide client SSL certificate bytes and private key + bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` + is None. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + if channel: + # Sanity check: Ensure that channel and credentials are not both + # provided. + credentials = False + + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + elif api_mtls_endpoint: + host = ( + api_mtls_endpoint + if ":" in api_mtls_endpoint + else api_mtls_endpoint + ":443" + ) + + # 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, + ) + + # Run the base constructor. + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes or self.AUTH_SCOPES, + ) + + self._stubs = {} + + @property + def grpc_channel(self) -> aio.Channel: + """Create the channel designed to connect to this service. + + This property caches on the instance; repeated calls return + the same channel. + """ + # Sanity check: Only create a new channel if we do not already + # have one. + if not hasattr(self, "_grpc_channel"): + self._grpc_channel = self.create_channel( + self._host, credentials=self._credentials, + ) + + # Return the channel from cache. + return self._grpc_channel + + @property + def create_budget( + self, + ) -> Callable[[budget_service.CreateBudgetRequest], Awaitable[budget_model.Budget]]: + r"""Return a callable for the create budget method over gRPC. + + Creates a new budget. See + Quotas + and limits for more information on the limits of the + number of budgets you can create. + + Returns: + Callable[[~.CreateBudgetRequest], + Awaitable[~.Budget]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_budget" not in self._stubs: + self._stubs["create_budget"] = self.grpc_channel.unary_unary( + "/google.cloud.billing.budgets.v1beta1.BudgetService/CreateBudget", + request_serializer=budget_service.CreateBudgetRequest.serialize, + response_deserializer=budget_model.Budget.deserialize, + ) + return self._stubs["create_budget"] + + @property + def update_budget( + self, + ) -> Callable[[budget_service.UpdateBudgetRequest], Awaitable[budget_model.Budget]]: + r"""Return a callable for the update budget method over gRPC. + + Updates a budget and returns the updated budget. + WARNING: There are some fields exposed on the Google + Cloud Console that aren't available on this API. Budget + fields that are not exposed in this API will not be + changed by this method. + + Returns: + Callable[[~.UpdateBudgetRequest], + Awaitable[~.Budget]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_budget" not in self._stubs: + self._stubs["update_budget"] = self.grpc_channel.unary_unary( + "/google.cloud.billing.budgets.v1beta1.BudgetService/UpdateBudget", + request_serializer=budget_service.UpdateBudgetRequest.serialize, + response_deserializer=budget_model.Budget.deserialize, + ) + return self._stubs["update_budget"] + + @property + def get_budget( + self, + ) -> Callable[[budget_service.GetBudgetRequest], Awaitable[budget_model.Budget]]: + r"""Return a callable for the get budget method over gRPC. + + Returns a budget. + WARNING: There are some fields exposed on the Google + Cloud Console that aren't available on this API. When + reading from the API, you will not see these fields in + the return value, though they may have been set in the + Cloud Console. + + Returns: + Callable[[~.GetBudgetRequest], + Awaitable[~.Budget]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_budget" not in self._stubs: + self._stubs["get_budget"] = self.grpc_channel.unary_unary( + "/google.cloud.billing.budgets.v1beta1.BudgetService/GetBudget", + request_serializer=budget_service.GetBudgetRequest.serialize, + response_deserializer=budget_model.Budget.deserialize, + ) + return self._stubs["get_budget"] + + @property + def list_budgets( + self, + ) -> Callable[ + [budget_service.ListBudgetsRequest], + Awaitable[budget_service.ListBudgetsResponse], + ]: + r"""Return a callable for the list budgets method over gRPC. + + Returns a list of budgets for a billing account. + WARNING: There are some fields exposed on the Google + Cloud Console that aren't available on this API. When + reading from the API, you will not see these fields in + the return value, though they may have been set in the + Cloud Console. + + Returns: + Callable[[~.ListBudgetsRequest], + Awaitable[~.ListBudgetsResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_budgets" not in self._stubs: + self._stubs["list_budgets"] = self.grpc_channel.unary_unary( + "/google.cloud.billing.budgets.v1beta1.BudgetService/ListBudgets", + request_serializer=budget_service.ListBudgetsRequest.serialize, + response_deserializer=budget_service.ListBudgetsResponse.deserialize, + ) + return self._stubs["list_budgets"] + + @property + def delete_budget( + self, + ) -> Callable[[budget_service.DeleteBudgetRequest], Awaitable[empty.Empty]]: + r"""Return a callable for the delete budget method over gRPC. + + Deletes a budget. Returns successfully if already + deleted. + + Returns: + Callable[[~.DeleteBudgetRequest], + Awaitable[~.Empty]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "delete_budget" not in self._stubs: + self._stubs["delete_budget"] = self.grpc_channel.unary_unary( + "/google.cloud.billing.budgets.v1beta1.BudgetService/DeleteBudget", + request_serializer=budget_service.DeleteBudgetRequest.serialize, + response_deserializer=empty.Empty.FromString, + ) + return self._stubs["delete_budget"] + + +__all__ = ("BudgetServiceGrpcAsyncIOTransport",) diff --git a/google/cloud/billing/budgets_v1beta1/types/__init__.py b/google/cloud/billing/budgets_v1beta1/types/__init__.py new file mode 100644 index 0000000..02b0409 --- /dev/null +++ b/google/cloud/billing/budgets_v1beta1/types/__init__.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from .budget_model import ( + Budget, + BudgetAmount, + LastPeriodAmount, + ThresholdRule, + AllUpdatesRule, + Filter, +) +from .budget_service import ( + CreateBudgetRequest, + UpdateBudgetRequest, + GetBudgetRequest, + ListBudgetsRequest, + ListBudgetsResponse, + DeleteBudgetRequest, +) + + +__all__ = ( + "Budget", + "BudgetAmount", + "LastPeriodAmount", + "ThresholdRule", + "AllUpdatesRule", + "Filter", + "CreateBudgetRequest", + "UpdateBudgetRequest", + "GetBudgetRequest", + "ListBudgetsRequest", + "ListBudgetsResponse", + "DeleteBudgetRequest", +) diff --git a/google/cloud/billing/budgets_v1beta1/types/budget_model.py b/google/cloud/billing/budgets_v1beta1/types/budget_model.py new file mode 100644 index 0000000..733068a --- /dev/null +++ b/google/cloud/billing/budgets_v1beta1/types/budget_model.py @@ -0,0 +1,247 @@ +# -*- coding: utf-8 -*- + +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import proto # type: ignore + + +from google.protobuf import struct_pb2 as struct # type: ignore +from google.type import money_pb2 as money # type: ignore + + +__protobuf__ = proto.module( + package="google.cloud.billing.budgets.v1beta1", + manifest={ + "Budget", + "BudgetAmount", + "LastPeriodAmount", + "ThresholdRule", + "AllUpdatesRule", + "Filter", + }, +) + + +class Budget(proto.Message): + r"""A budget is a plan that describes what you expect to spend on + Cloud projects, plus the rules to execute as spend is tracked + against that plan, (for example, send an alert when 90% of the + target spend is met). Currently all plans are monthly budgets so + the usage period(s) tracked are implied (calendar months of + usage back-to-back). + + Attributes: + name (str): + Output only. Resource name of the budget. The resource name + implies the scope of a budget. Values are of the form + ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. + display_name (str): + User data for display name in UI. + Validation: <= 60 chars. + budget_filter (~.budget_model.Filter): + Optional. Filters that define which resources + are used to compute the actual spend against the + budget. + amount (~.budget_model.BudgetAmount): + Required. Budgeted amount. + threshold_rules (Sequence[~.budget_model.ThresholdRule]): + Optional. Rules that trigger alerts + (notifications of thresholds being crossed) when + spend exceeds the specified percentages of the + budget. + all_updates_rule (~.budget_model.AllUpdatesRule): + Optional. Rules to apply to all updates to the actual spend, + regardless of the thresholds set in ``threshold_rules``. + etag (str): + Optional. Etag to validate that the object is + unchanged for a read-modify-write operation. + An empty etag will cause an update to overwrite + other changes. + """ + + name = proto.Field(proto.STRING, number=1) + + display_name = proto.Field(proto.STRING, number=2) + + budget_filter = proto.Field(proto.MESSAGE, number=3, message="Filter",) + + amount = proto.Field(proto.MESSAGE, number=4, message="BudgetAmount",) + + threshold_rules = proto.RepeatedField( + proto.MESSAGE, number=5, message="ThresholdRule", + ) + + all_updates_rule = proto.Field(proto.MESSAGE, number=6, message="AllUpdatesRule",) + + etag = proto.Field(proto.STRING, number=7) + + +class BudgetAmount(proto.Message): + r"""The budgeted amount for each usage period. + + Attributes: + specified_amount (~.money.Money): + A specified amount to use as the budget. ``currency_code`` + is optional. If specified, it must match the currency of the + billing account. The ``currency_code`` is provided on + output. + last_period_amount (~.budget_model.LastPeriodAmount): + Use the last period's actual spend as the + budget for the present period. + """ + + specified_amount = proto.Field(proto.MESSAGE, number=1, message=money.Money,) + + last_period_amount = proto.Field( + proto.MESSAGE, number=2, message="LastPeriodAmount", + ) + + +class LastPeriodAmount(proto.Message): + r"""Describes a budget amount targeted to last period's spend. + At this time, the amount is automatically 100% of last period's + spend; that is, there are no other options yet. + Future configuration will be described here (for example, + configuring a percentage of last period's spend). + """ + + +class ThresholdRule(proto.Message): + r"""ThresholdRule contains a definition of a threshold which triggers an + alert (a notification of a threshold being crossed) to be sent when + spend goes above the specified amount. Alerts are automatically + e-mailed to users with the Billing Account Administrator role or the + Billing Account User role. The thresholds here have no effect on + notifications sent to anything configured under + ``Budget.all_updates_rule``. + + Attributes: + threshold_percent (float): + Required. Send an alert when this threshold + is exceeded. This is a 1.0-based percentage, so + 0.5 = 50%. Validation: non-negative number. + spend_basis (~.budget_model.ThresholdRule.Basis): + Optional. The type of basis used to determine if spend has + passed the threshold. Behavior defaults to CURRENT_SPEND if + not set. + """ + + class Basis(proto.Enum): + r"""The type of basis used to determine if spend has passed the + threshold. + """ + BASIS_UNSPECIFIED = 0 + CURRENT_SPEND = 1 + FORECASTED_SPEND = 2 + + threshold_percent = proto.Field(proto.DOUBLE, number=1) + + spend_basis = proto.Field(proto.ENUM, number=2, enum=Basis,) + + +class AllUpdatesRule(proto.Message): + r"""AllUpdatesRule defines notifications that are sent on every + update to the billing account's spend, regardless of the + thresholds defined using threshold rules. + + Attributes: + pubsub_topic (str): + Required. The name of the Cloud Pub/Sub topic where budget + related messages will be published, in the form + ``projects/{project_id}/topics/{topic_id}``. Updates are + sent at regular intervals to the topic. The topic needs to + be created before the budget is created; see + https://cloud.google.com/billing/docs/how-to/budgets#manage-notifications + for more details. Caller is expected to have + ``pubsub.topics.setIamPolicy`` permission on the topic when + it's set for a budget, otherwise, the API call will fail + with PERMISSION_DENIED. See + https://cloud.google.com/pubsub/docs/access-control for more + details on Pub/Sub roles and permissions. + schema_version (str): + Required. The schema version of the notification. Only "1.0" + is accepted. It represents the JSON schema as defined in + https://cloud.google.com/billing/docs/how-to/budgets#notification_format + """ + + pubsub_topic = proto.Field(proto.STRING, number=1) + + schema_version = proto.Field(proto.STRING, number=2) + + +class Filter(proto.Message): + r"""A filter for a budget, limiting the scope of the cost to + calculate. + + Attributes: + projects (Sequence[str]): + Optional. A set of projects of the form + ``projects/{project}``, specifying that usage from only this + set of projects should be included in the budget. If + omitted, the report will include all usage for the billing + account, regardless of which project the usage occurred on. + Only zero or one project can be specified currently. + credit_types_treatment (~.budget_model.Filter.CreditTypesTreatment): + Optional. If not set, default behavior is + ``INCLUDE_ALL_CREDITS``. + services (Sequence[str]): + Optional. A set of services of the form + ``services/{service_id}``, specifying that usage from only + this set of services should be included in the budget. If + omitted, the report will include usage for all the services. + The service names are available through the Catalog API: + https://cloud.google.com/billing/v1/how-tos/catalog-api. + subaccounts (Sequence[str]): + Optional. A set of subaccounts of the form + ``billingAccounts/{account_id}``, specifying that usage from + only this set of subaccounts should be included in the + budget. If a subaccount is set to the name of the master + account, usage from the master account will be included. If + omitted, the report will include usage from the master + account and all subaccounts, if they exist. + labels (Sequence[~.budget_model.Filter.LabelsEntry]): + Optional. A single label and value pair + specifying that usage from only this set of + labeled resources should be included in the + budget. Multiple entries or multiple values per + entry are not allowed. If omitted, the report + will include all labeled and unlabeled usage. + """ + + class CreditTypesTreatment(proto.Enum): + r"""Specifies how credits should be treated when determining + spend for threshold calculations. + """ + CREDIT_TYPES_TREATMENT_UNSPECIFIED = 0 + INCLUDE_ALL_CREDITS = 1 + EXCLUDE_ALL_CREDITS = 2 + + projects = proto.RepeatedField(proto.STRING, number=1) + + credit_types_treatment = proto.Field( + proto.ENUM, number=4, enum=CreditTypesTreatment, + ) + + services = proto.RepeatedField(proto.STRING, number=3) + + subaccounts = proto.RepeatedField(proto.STRING, number=5) + + labels = proto.MapField( + proto.STRING, proto.MESSAGE, number=6, message=struct.ListValue, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/billing/budgets_v1beta1/types/budget_service.py b/google/cloud/billing/budgets_v1beta1/types/budget_service.py new file mode 100644 index 0000000..1961e31 --- /dev/null +++ b/google/cloud/billing/budgets_v1beta1/types/budget_service.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- + +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import proto # type: ignore + + +from google.cloud.billing.budgets_v1beta1.types import budget_model +from google.protobuf import field_mask_pb2 as field_mask # type: ignore + + +__protobuf__ = proto.module( + package="google.cloud.billing.budgets.v1beta1", + manifest={ + "CreateBudgetRequest", + "UpdateBudgetRequest", + "GetBudgetRequest", + "ListBudgetsRequest", + "ListBudgetsResponse", + "DeleteBudgetRequest", + }, +) + + +class CreateBudgetRequest(proto.Message): + r"""Request for CreateBudget + + Attributes: + parent (str): + Required. The name of the billing account to create the + budget in. Values are of the form + ``billingAccounts/{billingAccountId}``. + budget (~.budget_model.Budget): + Required. Budget to create. + """ + + parent = proto.Field(proto.STRING, number=1) + + budget = proto.Field(proto.MESSAGE, number=2, message=budget_model.Budget,) + + +class UpdateBudgetRequest(proto.Message): + r"""Request for UpdateBudget + + Attributes: + budget (~.budget_model.Budget): + Required. The updated budget object. + The budget to update is specified by the budget + name in the budget. + update_mask (~.field_mask.FieldMask): + Optional. Indicates which fields in the provided budget to + update. Read-only fields (such as ``name``) cannot be + changed. If this is not provided, then only fields with + non-default values from the request are updated. See + https://developers.google.com/protocol-buffers/docs/proto3#default + for more details about default values. + """ + + budget = proto.Field(proto.MESSAGE, number=1, message=budget_model.Budget,) + + update_mask = proto.Field(proto.MESSAGE, number=2, message=field_mask.FieldMask,) + + +class GetBudgetRequest(proto.Message): + r"""Request for GetBudget + + Attributes: + name (str): + Required. Name of budget to get. Values are of the form + ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. + """ + + name = proto.Field(proto.STRING, number=1) + + +class ListBudgetsRequest(proto.Message): + r"""Request for ListBudgets + + Attributes: + parent (str): + Required. Name of billing account to list budgets under. + Values are of the form + ``billingAccounts/{billingAccountId}``. + page_size (int): + Optional. The maximum number of budgets to + return per page. The default and maximum value + are 100. + page_token (str): + Optional. The value returned by the last + ``ListBudgetsResponse`` which indicates that this is a + continuation of a prior ``ListBudgets`` call, and that the + system should return the next page of data. + """ + + parent = proto.Field(proto.STRING, number=1) + + page_size = proto.Field(proto.INT32, number=2) + + page_token = proto.Field(proto.STRING, number=3) + + +class ListBudgetsResponse(proto.Message): + r"""Response for ListBudgets + + Attributes: + budgets (Sequence[~.budget_model.Budget]): + List of the budgets owned by the requested + billing account. + next_page_token (str): + If not empty, indicates that there may be more budgets that + match the request; this value should be passed in a new + ``ListBudgetsRequest``. + """ + + @property + def raw_page(self): + return self + + budgets = proto.RepeatedField(proto.MESSAGE, number=1, message=budget_model.Budget,) + + next_page_token = proto.Field(proto.STRING, number=2) + + +class DeleteBudgetRequest(proto.Message): + r"""Request for DeleteBudget + + Attributes: + name (str): + Required. Name of the budget to delete. Values are of the + form + ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. + """ + + name = proto.Field(proto.STRING, number=1) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/billing_budgets.py b/google/cloud/billing_budgets.py deleted file mode 100644 index fecd02b..0000000 --- a/google/cloud/billing_budgets.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# 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. - - -from __future__ import absolute_import - -from google.cloud.billing_budgets_v1beta1 import BudgetServiceClient -from google.cloud.billing_budgets_v1beta1 import enums -from google.cloud.billing_budgets_v1beta1 import types - - -__all__ = ( - "enums", - "types", - "BudgetServiceClient", -) diff --git a/google/cloud/billing_budgets_v1beta1/__init__.py b/google/cloud/billing_budgets_v1beta1/__init__.py deleted file mode 100644 index 0fcaa72..0000000 --- a/google/cloud/billing_budgets_v1beta1/__init__.py +++ /dev/null @@ -1,45 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# 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. - - -from __future__ import absolute_import -import sys -import warnings - -from google.cloud.billing_budgets_v1beta1 import types -from google.cloud.billing_budgets_v1beta1.gapic import budget_service_client -from google.cloud.billing_budgets_v1beta1.gapic import enums - - -if sys.version_info[:2] == (2, 7): - message = ( - "A future version of this library will drop support for Python 2.7. " - "More details about Python 2 support for Google Cloud Client Libraries " - "can be found at https://cloud.google.com/python/docs/python2-sunset/" - ) - warnings.warn(message, DeprecationWarning) - - -class BudgetServiceClient(budget_service_client.BudgetServiceClient): - __doc__ = budget_service_client.BudgetServiceClient.__doc__ - enums = enums - - -__all__ = ( - "enums", - "types", - "BudgetServiceClient", -) diff --git a/google/cloud/billing_budgets_v1beta1/gapic/__init__.py b/google/cloud/billing_budgets_v1beta1/gapic/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/google/cloud/billing_budgets_v1beta1/gapic/budget_service_client.py b/google/cloud/billing_budgets_v1beta1/gapic/budget_service_client.py deleted file mode 100644 index 793935a..0000000 --- a/google/cloud/billing_budgets_v1beta1/gapic/budget_service_client.py +++ /dev/null @@ -1,632 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# 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. - -"""Accesses the google.cloud.billing.budgets.v1beta1 BudgetService API.""" - -import functools -import pkg_resources -import warnings - -from google.oauth2 import service_account -import google.api_core.client_options -import google.api_core.gapic_v1.client_info -import google.api_core.gapic_v1.config -import google.api_core.gapic_v1.method -import google.api_core.gapic_v1.routing_header -import google.api_core.grpc_helpers -import google.api_core.page_iterator -import google.api_core.path_template -import grpc - -from google.cloud.billing_budgets_v1beta1.gapic import budget_service_client_config -from google.cloud.billing_budgets_v1beta1.gapic import enums -from google.cloud.billing_budgets_v1beta1.gapic.transports import ( - budget_service_grpc_transport, -) -from google.cloud.billing_budgets_v1beta1.proto import budget_model_pb2 -from google.cloud.billing_budgets_v1beta1.proto import budget_service_pb2 -from google.cloud.billing_budgets_v1beta1.proto import budget_service_pb2_grpc -from google.protobuf import empty_pb2 -from google.protobuf import field_mask_pb2 - - -_GAPIC_LIBRARY_VERSION = pkg_resources.get_distribution( - "google-cloud-billing-budgets", -).version - - -class BudgetServiceClient(object): - """ - BudgetService stores Cloud Billing budgets, which define a - budget plan and rules to execute as we track spend against that plan. - """ - - SERVICE_ADDRESS = "billingbudgets.googleapis.com:443" - """The default address of the service.""" - - # The name of the interface for this client. This is the key used to - # find the method configuration in the client_config dictionary. - _INTERFACE_NAME = "google.cloud.billing.budgets.v1beta1.BudgetService" - - @classmethod - def from_service_account_file(cls, filename, *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: - BudgetServiceClient: The constructed client. - """ - credentials = service_account.Credentials.from_service_account_file(filename) - kwargs["credentials"] = credentials - return cls(*args, **kwargs) - - from_service_account_json = from_service_account_file - - @classmethod - def billing_account_path(cls, billing_account): - """Return a fully-qualified billing_account string.""" - return google.api_core.path_template.expand( - "billingAccounts/{billing_account}", billing_account=billing_account, - ) - - @classmethod - def budget_path(cls, billing_account, budget): - """Return a fully-qualified budget string.""" - return google.api_core.path_template.expand( - "billingAccounts/{billing_account}/budgets/{budget}", - billing_account=billing_account, - budget=budget, - ) - - def __init__( - self, - transport=None, - channel=None, - credentials=None, - client_config=None, - client_info=None, - client_options=None, - ): - """Constructor. - - Args: - transport (Union[~.BudgetServiceGrpcTransport, - Callable[[~.Credentials, type], ~.BudgetServiceGrpcTransport]): A transport - instance, responsible for actually making the API calls. - The default transport uses the gRPC protocol. - This argument may also be a callable which returns a - transport instance. Callables will be sent the credentials - as the first argument and the default transport class as - the second argument. - channel (grpc.Channel): DEPRECATED. A ``Channel`` instance - through which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - This argument is mutually exclusive with providing a - transport instance to ``transport``; doing so will raise - an exception. - client_config (dict): DEPRECATED. A dictionary of call options for - each method. If not specified, the default configuration is used. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - client_options (Union[dict, google.api_core.client_options.ClientOptions]): - Client options used to set user options on the client. API Endpoint - should be set through client_options. - """ - # Raise deprecation warnings for things we want to go away. - if client_config is not None: - warnings.warn( - "The `client_config` argument is deprecated.", - PendingDeprecationWarning, - stacklevel=2, - ) - else: - client_config = budget_service_client_config.config - - if channel: - warnings.warn( - "The `channel` argument is deprecated; use " "`transport` instead.", - PendingDeprecationWarning, - stacklevel=2, - ) - - api_endpoint = self.SERVICE_ADDRESS - if client_options: - if type(client_options) == dict: - client_options = google.api_core.client_options.from_dict( - client_options - ) - if client_options.api_endpoint: - api_endpoint = client_options.api_endpoint - - # Instantiate the transport. - # The transport is responsible for handling serialization and - # deserialization and actually sending data to the service. - if transport: - if callable(transport): - self.transport = transport( - credentials=credentials, - default_class=budget_service_grpc_transport.BudgetServiceGrpcTransport, - address=api_endpoint, - ) - else: - if credentials: - raise ValueError( - "Received both a transport instance and " - "credentials; these are mutually exclusive." - ) - self.transport = transport - else: - self.transport = budget_service_grpc_transport.BudgetServiceGrpcTransport( - address=api_endpoint, channel=channel, credentials=credentials, - ) - - if client_info is None: - client_info = google.api_core.gapic_v1.client_info.ClientInfo( - gapic_version=_GAPIC_LIBRARY_VERSION, - ) - else: - client_info.gapic_version = _GAPIC_LIBRARY_VERSION - self._client_info = client_info - - # Parse out the default settings for retry and timeout for each RPC - # from the client configuration. - # (Ordinarily, these are the defaults specified in the `*_config.py` - # file next to this one.) - self._method_configs = google.api_core.gapic_v1.config.parse_method_configs( - client_config["interfaces"][self._INTERFACE_NAME], - ) - - # Save a dictionary of cached API call functions. - # These are the actual callables which invoke the proper - # transport methods, wrapped with `wrap_method` to add retry, - # timeout, and the like. - self._inner_api_calls = {} - - # Service calls - def create_budget( - self, - parent, - budget, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Creates a new budget. See - Quotas and limits - for more information on the limits of the number of budgets you can create. - - Example: - >>> from google.cloud import billing_budgets_v1beta1 - >>> - >>> client = billing_budgets_v1beta1.BudgetServiceClient() - >>> - >>> parent = client.billing_account_path('[BILLING_ACCOUNT]') - >>> - >>> # TODO: Initialize `budget`: - >>> budget = {} - >>> - >>> response = client.create_budget(parent, budget) - - Args: - parent (str): Required. The name of the billing account to create the budget in. - Values are of the form ``billingAccounts/{billingAccountId}``. - budget (Union[dict, ~google.cloud.billing_budgets_v1beta1.types.Budget]): Required. Budget to create. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.billing_budgets_v1beta1.types.Budget` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.billing_budgets_v1beta1.types.Budget` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "create_budget" not in self._inner_api_calls: - self._inner_api_calls[ - "create_budget" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.create_budget, - default_retry=self._method_configs["CreateBudget"].retry, - default_timeout=self._method_configs["CreateBudget"].timeout, - client_info=self._client_info, - ) - - request = budget_service_pb2.CreateBudgetRequest(parent=parent, budget=budget,) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("parent", parent)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["create_budget"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def update_budget( - self, - budget, - update_mask=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Updates a budget and returns the updated budget. - - WARNING: There are some fields exposed on the Google Cloud Console that - aren't available on this API. Budget fields that are not exposed in - this API will not be changed by this method. - - Example: - >>> from google.cloud import billing_budgets_v1beta1 - >>> - >>> client = billing_budgets_v1beta1.BudgetServiceClient() - >>> - >>> # TODO: Initialize `budget`: - >>> budget = {} - >>> - >>> response = client.update_budget(budget) - - Args: - budget (Union[dict, ~google.cloud.billing_budgets_v1beta1.types.Budget]): Required. The updated budget object. - The budget to update is specified by the budget name in the budget. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.billing_budgets_v1beta1.types.Budget` - update_mask (Union[dict, ~google.cloud.billing_budgets_v1beta1.types.FieldMask]): Optional. Indicates which fields in the provided budget to update. - Read-only fields (such as ``name``) cannot be changed. If this is not - provided, then only fields with non-default values from the request are - updated. See - https://developers.google.com/protocol-buffers/docs/proto3#default for - more details about default values. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.billing_budgets_v1beta1.types.FieldMask` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.billing_budgets_v1beta1.types.Budget` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "update_budget" not in self._inner_api_calls: - self._inner_api_calls[ - "update_budget" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.update_budget, - default_retry=self._method_configs["UpdateBudget"].retry, - default_timeout=self._method_configs["UpdateBudget"].timeout, - client_info=self._client_info, - ) - - request = budget_service_pb2.UpdateBudgetRequest( - budget=budget, update_mask=update_mask, - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("budget.name", budget.name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["update_budget"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def get_budget( - self, - name, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Returns a budget. - - WARNING: There are some fields exposed on the Google Cloud Console that - aren't available on this API. When reading from the API, you will not - see these fields in the return value, though they may have been set - in the Cloud Console. - - Example: - >>> from google.cloud import billing_budgets_v1beta1 - >>> - >>> client = billing_budgets_v1beta1.BudgetServiceClient() - >>> - >>> name = client.budget_path('[BILLING_ACCOUNT]', '[BUDGET]') - >>> - >>> response = client.get_budget(name) - - Args: - name (str): Required. Name of budget to get. Values are of the form - ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.billing_budgets_v1beta1.types.Budget` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "get_budget" not in self._inner_api_calls: - self._inner_api_calls[ - "get_budget" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.get_budget, - default_retry=self._method_configs["GetBudget"].retry, - default_timeout=self._method_configs["GetBudget"].timeout, - client_info=self._client_info, - ) - - request = budget_service_pb2.GetBudgetRequest(name=name,) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["get_budget"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def list_budgets( - self, - parent, - page_size=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Returns a list of budgets for a billing account. - - WARNING: There are some fields exposed on the Google Cloud Console that - aren't available on this API. When reading from the API, you will not - see these fields in the return value, though they may have been set - in the Cloud Console. - - Example: - >>> from google.cloud import billing_budgets_v1beta1 - >>> - >>> client = billing_budgets_v1beta1.BudgetServiceClient() - >>> - >>> parent = client.billing_account_path('[BILLING_ACCOUNT]') - >>> - >>> # Iterate over all results - >>> for element in client.list_budgets(parent): - ... # process element - ... pass - >>> - >>> - >>> # Alternatively: - >>> - >>> # Iterate over results one page at a time - >>> for page in client.list_budgets(parent).pages: - ... for element in page: - ... # process element - ... pass - - Args: - parent (str): Required. Name of billing account to list budgets under. Values are - of the form ``billingAccounts/{billingAccountId}``. - page_size (int): The maximum number of resources contained in the - underlying API response. If page streaming is performed per- - resource, this parameter does not affect the return value. If page - streaming is performed per-page, this determines the maximum number - of resources in a page. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.api_core.page_iterator.PageIterator` instance. - An iterable of :class:`~google.cloud.billing_budgets_v1beta1.types.Budget` instances. - You can also iterate over the pages of the response - using its `pages` property. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "list_budgets" not in self._inner_api_calls: - self._inner_api_calls[ - "list_budgets" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.list_budgets, - default_retry=self._method_configs["ListBudgets"].retry, - default_timeout=self._method_configs["ListBudgets"].timeout, - client_info=self._client_info, - ) - - request = budget_service_pb2.ListBudgetsRequest( - parent=parent, page_size=page_size, - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("parent", parent)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - iterator = google.api_core.page_iterator.GRPCIterator( - client=None, - method=functools.partial( - self._inner_api_calls["list_budgets"], - retry=retry, - timeout=timeout, - metadata=metadata, - ), - request=request, - items_field="budgets", - request_token_field="page_token", - response_token_field="next_page_token", - ) - return iterator - - def delete_budget( - self, - name, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Deletes a budget. Returns successfully if already deleted. - - Example: - >>> from google.cloud import billing_budgets_v1beta1 - >>> - >>> client = billing_budgets_v1beta1.BudgetServiceClient() - >>> - >>> name = client.budget_path('[BILLING_ACCOUNT]', '[BUDGET]') - >>> - >>> client.delete_budget(name) - - Args: - name (str): Required. Name of the budget to delete. Values are of the form - ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "delete_budget" not in self._inner_api_calls: - self._inner_api_calls[ - "delete_budget" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.delete_budget, - default_retry=self._method_configs["DeleteBudget"].retry, - default_timeout=self._method_configs["DeleteBudget"].timeout, - client_info=self._client_info, - ) - - request = budget_service_pb2.DeleteBudgetRequest(name=name,) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - self._inner_api_calls["delete_budget"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) diff --git a/google/cloud/billing_budgets_v1beta1/gapic/budget_service_client_config.py b/google/cloud/billing_budgets_v1beta1/gapic/budget_service_client_config.py deleted file mode 100644 index 1987acd..0000000 --- a/google/cloud/billing_budgets_v1beta1/gapic/budget_service_client_config.py +++ /dev/null @@ -1,48 +0,0 @@ -config = { - "interfaces": { - "google.cloud.billing.budgets.v1beta1.BudgetService": { - "retry_codes": { - "idempotent": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], - "non_idempotent": [], - }, - "retry_params": { - "default": { - "initial_retry_delay_millis": 100, - "retry_delay_multiplier": 1.3, - "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 20000, - "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 20000, - "total_timeout_millis": 600000, - } - }, - "methods": { - "CreateBudget": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "UpdateBudget": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "GetBudget": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "ListBudgets": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "DeleteBudget": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - }, - } - } -} diff --git a/google/cloud/billing_budgets_v1beta1/gapic/enums.py b/google/cloud/billing_budgets_v1beta1/gapic/enums.py deleted file mode 100644 index 5aae84c..0000000 --- a/google/cloud/billing_budgets_v1beta1/gapic/enums.py +++ /dev/null @@ -1,69 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# 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. - -"""Wrappers for protocol buffer enum types.""" - -import enum - - -class NullValue(enum.IntEnum): - """ - ``NullValue`` is a singleton enumeration to represent the null value - for the ``Value`` type union. - - The JSON representation for ``NullValue`` is JSON ``null``. - - Attributes: - NULL_VALUE (int): Null value. - """ - - NULL_VALUE = 0 - - -class Filter(object): - class CreditTypesTreatment(enum.IntEnum): - """ - Specifies how credits should be treated when determining spend for - threshold calculations. - - Attributes: - CREDIT_TYPES_TREATMENT_UNSPECIFIED (int) - INCLUDE_ALL_CREDITS (int): All types of credit are subtracted from the gross cost to determine the - spend for threshold calculations. - EXCLUDE_ALL_CREDITS (int): All types of credit are added to the net cost to determine the spend for - threshold calculations. - """ - - CREDIT_TYPES_TREATMENT_UNSPECIFIED = 0 - INCLUDE_ALL_CREDITS = 1 - EXCLUDE_ALL_CREDITS = 2 - - -class ThresholdRule(object): - class Basis(enum.IntEnum): - """ - The type of basis used to determine if spend has passed the threshold. - - Attributes: - BASIS_UNSPECIFIED (int): Unspecified threshold basis. - CURRENT_SPEND (int): Use current spend as the basis for comparison against the threshold. - FORECASTED_SPEND (int): Use forecasted spend for the period as the basis for comparison against - the threshold. - """ - - BASIS_UNSPECIFIED = 0 - CURRENT_SPEND = 1 - FORECASTED_SPEND = 2 diff --git a/google/cloud/billing_budgets_v1beta1/gapic/transports/__init__.py b/google/cloud/billing_budgets_v1beta1/gapic/transports/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/google/cloud/billing_budgets_v1beta1/gapic/transports/budget_service_grpc_transport.py b/google/cloud/billing_budgets_v1beta1/gapic/transports/budget_service_grpc_transport.py deleted file mode 100644 index f1188de..0000000 --- a/google/cloud/billing_budgets_v1beta1/gapic/transports/budget_service_grpc_transport.py +++ /dev/null @@ -1,192 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# 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. - - -import google.api_core.grpc_helpers - -from google.cloud.billing_budgets_v1beta1.proto import budget_service_pb2_grpc - - -class BudgetServiceGrpcTransport(object): - """gRPC transport class providing stubs for - google.cloud.billing.budgets.v1beta1 BudgetService API. - - The transport provides access to the raw gRPC stubs, - which can be used to take advantage of advanced - features of gRPC. - """ - - # The scopes needed to make gRPC calls to all of the methods defined - # in this service. - _OAUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) - - def __init__( - self, - channel=None, - credentials=None, - address="billingbudgets.googleapis.com:443", - ): - """Instantiate the transport class. - - Args: - channel (grpc.Channel): A ``Channel`` instance through - which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - address (str): The address where the service is hosted. - """ - # If both `channel` and `credentials` are specified, raise an - # exception (channels come with credentials baked in already). - if channel is not None and credentials is not None: - raise ValueError( - "The `channel` and `credentials` arguments are mutually " "exclusive.", - ) - - # Create the channel. - if channel is None: - channel = self.create_channel( - address=address, - credentials=credentials, - options={ - "grpc.max_send_message_length": -1, - "grpc.max_receive_message_length": -1, - }.items(), - ) - - self._channel = channel - - # gRPC uses objects called "stubs" that are bound to the - # channel and provide a basic method for each RPC. - self._stubs = { - "budget_service_stub": budget_service_pb2_grpc.BudgetServiceStub(channel), - } - - @classmethod - def create_channel( - cls, address="billingbudgets.googleapis.com:443", credentials=None, **kwargs - ): - """Create and return a gRPC channel object. - - Args: - address (str): The host for the channel to use. - credentials (~.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If - none are specified, the client will attempt to ascertain - the credentials from the environment. - kwargs (dict): Keyword arguments, which are passed to the - channel creation. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return google.api_core.grpc_helpers.create_channel( - address, credentials=credentials, scopes=cls._OAUTH_SCOPES, **kwargs - ) - - @property - def channel(self): - """The gRPC channel used by the transport. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return self._channel - - @property - def create_budget(self): - """Return the gRPC stub for :meth:`BudgetServiceClient.create_budget`. - - Creates a new budget. See - Quotas and limits - for more information on the limits of the number of budgets you can create. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["budget_service_stub"].CreateBudget - - @property - def update_budget(self): - """Return the gRPC stub for :meth:`BudgetServiceClient.update_budget`. - - Updates a budget and returns the updated budget. - - WARNING: There are some fields exposed on the Google Cloud Console that - aren't available on this API. Budget fields that are not exposed in - this API will not be changed by this method. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["budget_service_stub"].UpdateBudget - - @property - def get_budget(self): - """Return the gRPC stub for :meth:`BudgetServiceClient.get_budget`. - - Returns a budget. - - WARNING: There are some fields exposed on the Google Cloud Console that - aren't available on this API. When reading from the API, you will not - see these fields in the return value, though they may have been set - in the Cloud Console. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["budget_service_stub"].GetBudget - - @property - def list_budgets(self): - """Return the gRPC stub for :meth:`BudgetServiceClient.list_budgets`. - - Returns a list of budgets for a billing account. - - WARNING: There are some fields exposed on the Google Cloud Console that - aren't available on this API. When reading from the API, you will not - see these fields in the return value, though they may have been set - in the Cloud Console. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["budget_service_stub"].ListBudgets - - @property - def delete_budget(self): - """Return the gRPC stub for :meth:`BudgetServiceClient.delete_budget`. - - Deletes a budget. Returns successfully if already deleted. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["budget_service_stub"].DeleteBudget diff --git a/google/cloud/billing_budgets_v1beta1/proto/__init__.py b/google/cloud/billing_budgets_v1beta1/proto/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2.py b/google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2.py deleted file mode 100644 index 6f8987a..0000000 --- a/google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2.py +++ /dev/null @@ -1,915 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/cloud/billing_budgets_v1beta1/proto/budget_model.proto - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 -from google.api import resource_pb2 as google_dot_api_dot_resource__pb2 -from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 -from google.type import money_pb2 as google_dot_type_dot_money__pb2 - - -DESCRIPTOR = _descriptor.FileDescriptor( - name="google/cloud/billing_budgets_v1beta1/proto/budget_model.proto", - package="google.cloud.billing.budgets.v1beta1", - syntax="proto3", - serialized_options=b"\n(com.google.cloud.billing.budgets.v1beta1P\001ZKgoogle.golang.org/genproto/googleapis/cloud/billing/budgets/v1beta1;budgets", - create_key=_descriptor._internal_create_key, - serialized_pb=b'\n=google/cloud/billing_budgets_v1beta1/proto/budget_model.proto\x12$google.cloud.billing.budgets.v1beta1\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x17google/type/money.proto"\xde\x03\n\x06\x42udget\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x03\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12H\n\rbudget_filter\x18\x03 \x01(\x0b\x32,.google.cloud.billing.budgets.v1beta1.FilterB\x03\xe0\x41\x01\x12G\n\x06\x61mount\x18\x04 \x01(\x0b\x32\x32.google.cloud.billing.budgets.v1beta1.BudgetAmountB\x03\xe0\x41\x02\x12Q\n\x0fthreshold_rules\x18\x05 \x03(\x0b\x32\x33.google.cloud.billing.budgets.v1beta1.ThresholdRuleB\x03\xe0\x41\x01\x12S\n\x10\x61ll_updates_rule\x18\x06 \x01(\x0b\x32\x34.google.cloud.billing.budgets.v1beta1.AllUpdatesRuleB\x03\xe0\x41\x01\x12\x11\n\x04\x65tag\x18\x07 \x01(\tB\x03\xe0\x41\x01:]\xea\x41Z\n$billingbudgets.googleapis.com/Budget\x12\x32\x62illingAccounts/{billing_account}/budgets/{budget}"\xa5\x01\n\x0c\x42udgetAmount\x12.\n\x10specified_amount\x18\x01 \x01(\x0b\x32\x12.google.type.MoneyH\x00\x12T\n\x12last_period_amount\x18\x02 \x01(\x0b\x32\x36.google.cloud.billing.budgets.v1beta1.LastPeriodAmountH\x00\x42\x0f\n\rbudget_amount"\x12\n\x10LastPeriodAmount"\xcd\x01\n\rThresholdRule\x12\x1e\n\x11threshold_percent\x18\x01 \x01(\x01\x42\x03\xe0\x41\x02\x12S\n\x0bspend_basis\x18\x02 \x01(\x0e\x32\x39.google.cloud.billing.budgets.v1beta1.ThresholdRule.BasisB\x03\xe0\x41\x01"G\n\x05\x42\x61sis\x12\x15\n\x11\x42\x41SIS_UNSPECIFIED\x10\x00\x12\x11\n\rCURRENT_SPEND\x10\x01\x12\x14\n\x10\x46ORECASTED_SPEND\x10\x02"H\n\x0e\x41llUpdatesRule\x12\x19\n\x0cpubsub_topic\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x1b\n\x0eschema_version\x18\x02 \x01(\tB\x03\xe0\x41\x02"\xc4\x03\n\x06\x46ilter\x12\x15\n\x08projects\x18\x01 \x03(\tB\x03\xe0\x41\x01\x12\x66\n\x16\x63redit_types_treatment\x18\x04 \x01(\x0e\x32\x41.google.cloud.billing.budgets.v1beta1.Filter.CreditTypesTreatmentB\x03\xe0\x41\x01\x12\x15\n\x08services\x18\x03 \x03(\tB\x03\xe0\x41\x01\x12\x18\n\x0bsubaccounts\x18\x05 \x03(\tB\x03\xe0\x41\x01\x12M\n\x06labels\x18\x06 \x03(\x0b\x32\x38.google.cloud.billing.budgets.v1beta1.Filter.LabelsEntryB\x03\xe0\x41\x01\x1aI\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.ListValue:\x02\x38\x01"p\n\x14\x43reditTypesTreatment\x12&\n"CREDIT_TYPES_TREATMENT_UNSPECIFIED\x10\x00\x12\x17\n\x13INCLUDE_ALL_CREDITS\x10\x01\x12\x17\n\x13\x45XCLUDE_ALL_CREDITS\x10\x02\x42y\n(com.google.cloud.billing.budgets.v1beta1P\x01ZKgoogle.golang.org/genproto/googleapis/cloud/billing/budgets/v1beta1;budgetsb\x06proto3', - dependencies=[ - google_dot_api_dot_field__behavior__pb2.DESCRIPTOR, - google_dot_api_dot_resource__pb2.DESCRIPTOR, - google_dot_protobuf_dot_struct__pb2.DESCRIPTOR, - google_dot_type_dot_money__pb2.DESCRIPTOR, - ], -) - - -_THRESHOLDRULE_BASIS = _descriptor.EnumDescriptor( - name="Basis", - full_name="google.cloud.billing.budgets.v1beta1.ThresholdRule.Basis", - filename=None, - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - values=[ - _descriptor.EnumValueDescriptor( - name="BASIS_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key, - ), - _descriptor.EnumValueDescriptor( - name="CURRENT_SPEND", - index=1, - number=1, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key, - ), - _descriptor.EnumValueDescriptor( - name="FORECASTED_SPEND", - index=2, - number=2, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key, - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=1022, - serialized_end=1093, -) -_sym_db.RegisterEnumDescriptor(_THRESHOLDRULE_BASIS) - -_FILTER_CREDITTYPESTREATMENT = _descriptor.EnumDescriptor( - name="CreditTypesTreatment", - full_name="google.cloud.billing.budgets.v1beta1.Filter.CreditTypesTreatment", - filename=None, - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - values=[ - _descriptor.EnumValueDescriptor( - name="CREDIT_TYPES_TREATMENT_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key, - ), - _descriptor.EnumValueDescriptor( - name="INCLUDE_ALL_CREDITS", - index=1, - number=1, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key, - ), - _descriptor.EnumValueDescriptor( - name="EXCLUDE_ALL_CREDITS", - index=2, - number=2, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key, - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=1510, - serialized_end=1622, -) -_sym_db.RegisterEnumDescriptor(_FILTER_CREDITTYPESTREATMENT) - - -_BUDGET = _descriptor.Descriptor( - name="Budget", - full_name="google.cloud.billing.budgets.v1beta1.Budget", - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.cloud.billing.budgets.v1beta1.Budget.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=b"".decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\003", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="display_name", - full_name="google.cloud.billing.budgets.v1beta1.Budget.display_name", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=b"".decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="budget_filter", - full_name="google.cloud.billing.budgets.v1beta1.Budget.budget_filter", - index=2, - number=3, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\001", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="amount", - full_name="google.cloud.billing.budgets.v1beta1.Budget.amount", - index=3, - number=4, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\002", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="threshold_rules", - full_name="google.cloud.billing.budgets.v1beta1.Budget.threshold_rules", - index=4, - number=5, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\001", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="all_updates_rule", - full_name="google.cloud.billing.budgets.v1beta1.Budget.all_updates_rule", - index=5, - number=6, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\001", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="etag", - full_name="google.cloud.billing.budgets.v1beta1.Budget.etag", - index=6, - number=7, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=b"".decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\001", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=b"\352AZ\n$billingbudgets.googleapis.com/Budget\0222billingAccounts/{billing_account}/budgets/{budget}", - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=219, - serialized_end=697, -) - - -_BUDGETAMOUNT = _descriptor.Descriptor( - name="BudgetAmount", - full_name="google.cloud.billing.budgets.v1beta1.BudgetAmount", - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name="specified_amount", - full_name="google.cloud.billing.budgets.v1beta1.BudgetAmount.specified_amount", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="last_period_amount", - full_name="google.cloud.billing.budgets.v1beta1.BudgetAmount.last_period_amount", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[ - _descriptor.OneofDescriptor( - name="budget_amount", - full_name="google.cloud.billing.budgets.v1beta1.BudgetAmount.budget_amount", - index=0, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[], - ), - ], - serialized_start=700, - serialized_end=865, -) - - -_LASTPERIODAMOUNT = _descriptor.Descriptor( - name="LastPeriodAmount", - full_name="google.cloud.billing.budgets.v1beta1.LastPeriodAmount", - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=867, - serialized_end=885, -) - - -_THRESHOLDRULE = _descriptor.Descriptor( - name="ThresholdRule", - full_name="google.cloud.billing.budgets.v1beta1.ThresholdRule", - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name="threshold_percent", - full_name="google.cloud.billing.budgets.v1beta1.ThresholdRule.threshold_percent", - index=0, - number=1, - type=1, - cpp_type=5, - label=1, - has_default_value=False, - default_value=float(0), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\002", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="spend_basis", - full_name="google.cloud.billing.budgets.v1beta1.ThresholdRule.spend_basis", - index=1, - number=2, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\001", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - ], - extensions=[], - nested_types=[], - enum_types=[_THRESHOLDRULE_BASIS,], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=888, - serialized_end=1093, -) - - -_ALLUPDATESRULE = _descriptor.Descriptor( - name="AllUpdatesRule", - full_name="google.cloud.billing.budgets.v1beta1.AllUpdatesRule", - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name="pubsub_topic", - full_name="google.cloud.billing.budgets.v1beta1.AllUpdatesRule.pubsub_topic", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=b"".decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\002", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="schema_version", - full_name="google.cloud.billing.budgets.v1beta1.AllUpdatesRule.schema_version", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=b"".decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\002", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1095, - serialized_end=1167, -) - - -_FILTER_LABELSENTRY = _descriptor.Descriptor( - name="LabelsEntry", - full_name="google.cloud.billing.budgets.v1beta1.Filter.LabelsEntry", - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name="key", - full_name="google.cloud.billing.budgets.v1beta1.Filter.LabelsEntry.key", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=b"".decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="value", - full_name="google.cloud.billing.budgets.v1beta1.Filter.LabelsEntry.value", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=b"8\001", - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1435, - serialized_end=1508, -) - -_FILTER = _descriptor.Descriptor( - name="Filter", - full_name="google.cloud.billing.budgets.v1beta1.Filter", - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name="projects", - full_name="google.cloud.billing.budgets.v1beta1.Filter.projects", - index=0, - number=1, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\001", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="credit_types_treatment", - full_name="google.cloud.billing.budgets.v1beta1.Filter.credit_types_treatment", - index=1, - number=4, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\001", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="services", - full_name="google.cloud.billing.budgets.v1beta1.Filter.services", - index=2, - number=3, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\001", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="subaccounts", - full_name="google.cloud.billing.budgets.v1beta1.Filter.subaccounts", - index=3, - number=5, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\001", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="labels", - full_name="google.cloud.billing.budgets.v1beta1.Filter.labels", - index=4, - number=6, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\001", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - ], - extensions=[], - nested_types=[_FILTER_LABELSENTRY,], - enum_types=[_FILTER_CREDITTYPESTREATMENT,], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1170, - serialized_end=1622, -) - -_BUDGET.fields_by_name["budget_filter"].message_type = _FILTER -_BUDGET.fields_by_name["amount"].message_type = _BUDGETAMOUNT -_BUDGET.fields_by_name["threshold_rules"].message_type = _THRESHOLDRULE -_BUDGET.fields_by_name["all_updates_rule"].message_type = _ALLUPDATESRULE -_BUDGETAMOUNT.fields_by_name[ - "specified_amount" -].message_type = google_dot_type_dot_money__pb2._MONEY -_BUDGETAMOUNT.fields_by_name["last_period_amount"].message_type = _LASTPERIODAMOUNT -_BUDGETAMOUNT.oneofs_by_name["budget_amount"].fields.append( - _BUDGETAMOUNT.fields_by_name["specified_amount"] -) -_BUDGETAMOUNT.fields_by_name[ - "specified_amount" -].containing_oneof = _BUDGETAMOUNT.oneofs_by_name["budget_amount"] -_BUDGETAMOUNT.oneofs_by_name["budget_amount"].fields.append( - _BUDGETAMOUNT.fields_by_name["last_period_amount"] -) -_BUDGETAMOUNT.fields_by_name[ - "last_period_amount" -].containing_oneof = _BUDGETAMOUNT.oneofs_by_name["budget_amount"] -_THRESHOLDRULE.fields_by_name["spend_basis"].enum_type = _THRESHOLDRULE_BASIS -_THRESHOLDRULE_BASIS.containing_type = _THRESHOLDRULE -_FILTER_LABELSENTRY.fields_by_name[ - "value" -].message_type = google_dot_protobuf_dot_struct__pb2._LISTVALUE -_FILTER_LABELSENTRY.containing_type = _FILTER -_FILTER.fields_by_name[ - "credit_types_treatment" -].enum_type = _FILTER_CREDITTYPESTREATMENT -_FILTER.fields_by_name["labels"].message_type = _FILTER_LABELSENTRY -_FILTER_CREDITTYPESTREATMENT.containing_type = _FILTER -DESCRIPTOR.message_types_by_name["Budget"] = _BUDGET -DESCRIPTOR.message_types_by_name["BudgetAmount"] = _BUDGETAMOUNT -DESCRIPTOR.message_types_by_name["LastPeriodAmount"] = _LASTPERIODAMOUNT -DESCRIPTOR.message_types_by_name["ThresholdRule"] = _THRESHOLDRULE -DESCRIPTOR.message_types_by_name["AllUpdatesRule"] = _ALLUPDATESRULE -DESCRIPTOR.message_types_by_name["Filter"] = _FILTER -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -Budget = _reflection.GeneratedProtocolMessageType( - "Budget", - (_message.Message,), - { - "DESCRIPTOR": _BUDGET, - "__module__": "google.cloud.billing_budgets_v1beta1.proto.budget_model_pb2", - "__doc__": """A budget is a plan that describes what you expect to spend on Cloud - projects, plus the rules to execute as spend is tracked against that - plan, (for example, send an alert when 90% of the target spend is - met). Currently all plans are monthly budgets so the usage period(s) - tracked are implied (calendar months of usage back-to-back). - - Attributes: - name: - Output only. Resource name of the budget. The resource name - implies the scope of a budget. Values are of the form - ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. - display_name: - User data for display name in UI. Validation: <= 60 chars. - budget_filter: - Optional. Filters that define which resources are used to - compute the actual spend against the budget. - amount: - Required. Budgeted amount. - threshold_rules: - Optional. Rules that trigger alerts (notifications of - thresholds being crossed) when spend exceeds the specified - percentages of the budget. - all_updates_rule: - Optional. Rules to apply to all updates to the actual spend, - regardless of the thresholds set in ``threshold_rules``. - etag: - Optional. Etag to validate that the object is unchanged for a - read-modify-write operation. An empty etag will cause an - update to overwrite other changes. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.Budget) - }, -) -_sym_db.RegisterMessage(Budget) - -BudgetAmount = _reflection.GeneratedProtocolMessageType( - "BudgetAmount", - (_message.Message,), - { - "DESCRIPTOR": _BUDGETAMOUNT, - "__module__": "google.cloud.billing_budgets_v1beta1.proto.budget_model_pb2", - "__doc__": """The budgeted amount for each usage period. - - Attributes: - budget_amount: - Specification for what amount to use as the budget. - specified_amount: - A specified amount to use as the budget. ``currency_code`` is - optional. If specified, it must match the currency of the - billing account. The ``currency_code`` is provided on output. - last_period_amount: - Use the last period’s actual spend as the budget for the - present period. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.BudgetAmount) - }, -) -_sym_db.RegisterMessage(BudgetAmount) - -LastPeriodAmount = _reflection.GeneratedProtocolMessageType( - "LastPeriodAmount", - (_message.Message,), - { - "DESCRIPTOR": _LASTPERIODAMOUNT, - "__module__": "google.cloud.billing_budgets_v1beta1.proto.budget_model_pb2", - "__doc__": """Describes a budget amount targeted to last period’s spend. At this - time, the amount is automatically 100% of last period’s spend; that - is, there are no other options yet. Future configuration will be - described here (for example, configuring a percentage of last period’s - spend).""", - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.LastPeriodAmount) - }, -) -_sym_db.RegisterMessage(LastPeriodAmount) - -ThresholdRule = _reflection.GeneratedProtocolMessageType( - "ThresholdRule", - (_message.Message,), - { - "DESCRIPTOR": _THRESHOLDRULE, - "__module__": "google.cloud.billing_budgets_v1beta1.proto.budget_model_pb2", - "__doc__": """ThresholdRule contains a definition of a threshold which triggers an - alert (a notification of a threshold being crossed) to be sent when - spend goes above the specified amount. Alerts are automatically - e-mailed to users with the Billing Account Administrator role or the - Billing Account User role. The thresholds here have no effect on - notifications sent to anything configured under - ``Budget.all_updates_rule``. - - Attributes: - threshold_percent: - Required. Send an alert when this threshold is exceeded. This - is a 1.0-based percentage, so 0.5 = 50%. Validation: non- - negative number. - spend_basis: - Optional. The type of basis used to determine if spend has - passed the threshold. Behavior defaults to CURRENT_SPEND if - not set. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.ThresholdRule) - }, -) -_sym_db.RegisterMessage(ThresholdRule) - -AllUpdatesRule = _reflection.GeneratedProtocolMessageType( - "AllUpdatesRule", - (_message.Message,), - { - "DESCRIPTOR": _ALLUPDATESRULE, - "__module__": "google.cloud.billing_budgets_v1beta1.proto.budget_model_pb2", - "__doc__": """AllUpdatesRule defines notifications that are sent on every update to - the billing account’s spend, regardless of the thresholds defined - using threshold rules. - - Attributes: - pubsub_topic: - Required. The name of the Cloud Pub/Sub topic where budget - related messages will be published, in the form - ``projects/{project_id}/topics/{topic_id}``. Updates are sent - at regular intervals to the topic. The topic needs to be - created before the budget is created; see - https://cloud.google.com/billing/docs/how-to/budgets#manage- - notifications for more details. Caller is expected to have - ``pubsub.topics.setIamPolicy`` permission on the topic when - it’s set for a budget, otherwise, the API call will fail with - PERMISSION_DENIED. See - https://cloud.google.com/pubsub/docs/access-control for more - details on Pub/Sub roles and permissions. - schema_version: - Required. The schema version of the notification. Only “1.0” - is accepted. It represents the JSON schema as defined in - https://cloud.google.com/billing/docs/how- - to/budgets#notification_format - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.AllUpdatesRule) - }, -) -_sym_db.RegisterMessage(AllUpdatesRule) - -Filter = _reflection.GeneratedProtocolMessageType( - "Filter", - (_message.Message,), - { - "LabelsEntry": _reflection.GeneratedProtocolMessageType( - "LabelsEntry", - (_message.Message,), - { - "DESCRIPTOR": _FILTER_LABELSENTRY, - "__module__": "google.cloud.billing_budgets_v1beta1.proto.budget_model_pb2" - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.Filter.LabelsEntry) - }, - ), - "DESCRIPTOR": _FILTER, - "__module__": "google.cloud.billing_budgets_v1beta1.proto.budget_model_pb2", - "__doc__": """A filter for a budget, limiting the scope of the cost to calculate. - - Attributes: - projects: - Optional. A set of projects of the form - ``projects/{project}``, specifying that usage from only this - set of projects should be included in the budget. If omitted, - the report will include all usage for the billing account, - regardless of which project the usage occurred on. Only zero - or one project can be specified currently. - credit_types_treatment: - Optional. If not set, default behavior is - ``INCLUDE_ALL_CREDITS``. - services: - Optional. A set of services of the form - ``services/{service_id}``, specifying that usage from only - this set of services should be included in the budget. If - omitted, the report will include usage for all the services. - The service names are available through the Catalog API: - https://cloud.google.com/billing/v1/how-tos/catalog-api. - subaccounts: - Optional. A set of subaccounts of the form - ``billingAccounts/{account_id}``, specifying that usage from - only this set of subaccounts should be included in the budget. - If a subaccount is set to the name of the master account, - usage from the master account will be included. If omitted, - the report will include usage from the master account and all - subaccounts, if they exist. - labels: - Optional. A single label and value pair specifying that usage - from only this set of labeled resources should be included in - the budget. Multiple entries or multiple values per entry are - not allowed. If omitted, the report will include all labeled - and unlabeled usage. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.Filter) - }, -) -_sym_db.RegisterMessage(Filter) -_sym_db.RegisterMessage(Filter.LabelsEntry) - - -DESCRIPTOR._options = None -_BUDGET.fields_by_name["name"]._options = None -_BUDGET.fields_by_name["budget_filter"]._options = None -_BUDGET.fields_by_name["amount"]._options = None -_BUDGET.fields_by_name["threshold_rules"]._options = None -_BUDGET.fields_by_name["all_updates_rule"]._options = None -_BUDGET.fields_by_name["etag"]._options = None -_BUDGET._options = None -_THRESHOLDRULE.fields_by_name["threshold_percent"]._options = None -_THRESHOLDRULE.fields_by_name["spend_basis"]._options = None -_ALLUPDATESRULE.fields_by_name["pubsub_topic"]._options = None -_ALLUPDATESRULE.fields_by_name["schema_version"]._options = None -_FILTER_LABELSENTRY._options = None -_FILTER.fields_by_name["projects"]._options = None -_FILTER.fields_by_name["credit_types_treatment"]._options = None -_FILTER.fields_by_name["services"]._options = None -_FILTER.fields_by_name["subaccounts"]._options = None -_FILTER.fields_by_name["labels"]._options = None -# @@protoc_insertion_point(module_scope) diff --git a/google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2_grpc.py b/google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2_grpc.py deleted file mode 100644 index 07cb78f..0000000 --- a/google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2_grpc.py +++ /dev/null @@ -1,2 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc diff --git a/google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2.py b/google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2.py deleted file mode 100644 index 9a8f5d9..0000000 --- a/google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2.py +++ /dev/null @@ -1,619 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/cloud/billing_budgets_v1beta1/proto/budget_service.proto - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 -from google.api import client_pb2 as google_dot_api_dot_client__pb2 -from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 -from google.api import resource_pb2 as google_dot_api_dot_resource__pb2 -from google.cloud.billing_budgets_v1beta1.proto import ( - budget_model_pb2 as google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__model__pb2, -) -from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 -from google.protobuf import field_mask_pb2 as google_dot_protobuf_dot_field__mask__pb2 - - -DESCRIPTOR = _descriptor.FileDescriptor( - name="google/cloud/billing_budgets_v1beta1/proto/budget_service.proto", - package="google.cloud.billing.budgets.v1beta1", - syntax="proto3", - serialized_options=b"\n(com.google.cloud.billing.budgets.v1beta1P\001ZKgoogle.golang.org/genproto/googleapis/cloud/billing/budgets/v1beta1;budgets", - create_key=_descriptor._internal_create_key, - serialized_pb=b'\n?google/cloud/billing_budgets_v1beta1/proto/budget_service.proto\x12$google.cloud.billing.budgets.v1beta1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a=google/cloud/billing_budgets_v1beta1/proto/budget_model.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto"\x96\x01\n\x13\x43reateBudgetRequest\x12<\n\x06parent\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\x12$billingbudgets.googleapis.com/Budget\x12\x41\n\x06\x62udget\x18\x02 \x01(\x0b\x32,.google.cloud.billing.budgets.v1beta1.BudgetB\x03\xe0\x41\x02"\x8e\x01\n\x13UpdateBudgetRequest\x12\x41\n\x06\x62udget\x18\x01 \x01(\x0b\x32,.google.cloud.billing.budgets.v1beta1.BudgetB\x03\xe0\x41\x02\x12\x34\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x01"N\n\x10GetBudgetRequest\x12:\n\x04name\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$billingbudgets.googleapis.com/Budget"\x83\x01\n\x12ListBudgetsRequest\x12<\n\x06parent\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\x12$billingbudgets.googleapis.com/Budget\x12\x16\n\tpage_size\x18\x02 \x01(\x05\x42\x03\xe0\x41\x01\x12\x17\n\npage_token\x18\x03 \x01(\tB\x03\xe0\x41\x01"m\n\x13ListBudgetsResponse\x12=\n\x07\x62udgets\x18\x01 \x03(\x0b\x32,.google.cloud.billing.budgets.v1beta1.Budget\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"Q\n\x13\x44\x65leteBudgetRequest\x12:\n\x04name\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$billingbudgets.googleapis.com/Budget2\xc9\x07\n\rBudgetService\x12\xaf\x01\n\x0c\x43reateBudget\x12\x39.google.cloud.billing.budgets.v1beta1.CreateBudgetRequest\x1a,.google.cloud.billing.budgets.v1beta1.Budget"6\x82\xd3\xe4\x93\x02\x30"+/v1beta1/{parent=billingAccounts/*}/budgets:\x01*\x12\xb6\x01\n\x0cUpdateBudget\x12\x39.google.cloud.billing.budgets.v1beta1.UpdateBudgetRequest\x1a,.google.cloud.billing.budgets.v1beta1.Budget"=\x82\xd3\xe4\x93\x02\x37\x32\x32/v1beta1/{budget.name=billingAccounts/*/budgets/*}:\x01*\x12\xa6\x01\n\tGetBudget\x12\x36.google.cloud.billing.budgets.v1beta1.GetBudgetRequest\x1a,.google.cloud.billing.budgets.v1beta1.Budget"3\x82\xd3\xe4\x93\x02-\x12+/v1beta1/{name=billingAccounts/*/budgets/*}\x12\xb7\x01\n\x0bListBudgets\x12\x38.google.cloud.billing.budgets.v1beta1.ListBudgetsRequest\x1a\x39.google.cloud.billing.budgets.v1beta1.ListBudgetsResponse"3\x82\xd3\xe4\x93\x02-\x12+/v1beta1/{parent=billingAccounts/*}/budgets\x12\x96\x01\n\x0c\x44\x65leteBudget\x12\x39.google.cloud.billing.budgets.v1beta1.DeleteBudgetRequest\x1a\x16.google.protobuf.Empty"3\x82\xd3\xe4\x93\x02-*+/v1beta1/{name=billingAccounts/*/budgets/*}\x1aQ\xca\x41\x1d\x62illingbudgets.googleapis.com\xd2\x41.https://www.googleapis.com/auth/cloud-platformBy\n(com.google.cloud.billing.budgets.v1beta1P\x01ZKgoogle.golang.org/genproto/googleapis/cloud/billing/budgets/v1beta1;budgetsb\x06proto3', - dependencies=[ - google_dot_api_dot_annotations__pb2.DESCRIPTOR, - google_dot_api_dot_client__pb2.DESCRIPTOR, - google_dot_api_dot_field__behavior__pb2.DESCRIPTOR, - google_dot_api_dot_resource__pb2.DESCRIPTOR, - google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__model__pb2.DESCRIPTOR, - google_dot_protobuf_dot_empty__pb2.DESCRIPTOR, - google_dot_protobuf_dot_field__mask__pb2.DESCRIPTOR, - ], -) - - -_CREATEBUDGETREQUEST = _descriptor.Descriptor( - name="CreateBudgetRequest", - full_name="google.cloud.billing.budgets.v1beta1.CreateBudgetRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name="parent", - full_name="google.cloud.billing.budgets.v1beta1.CreateBudgetRequest.parent", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=b"".decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\002\372A&\022$billingbudgets.googleapis.com/Budget", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="budget", - full_name="google.cloud.billing.budgets.v1beta1.CreateBudgetRequest.budget", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\002", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=347, - serialized_end=497, -) - - -_UPDATEBUDGETREQUEST = _descriptor.Descriptor( - name="UpdateBudgetRequest", - full_name="google.cloud.billing.budgets.v1beta1.UpdateBudgetRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name="budget", - full_name="google.cloud.billing.budgets.v1beta1.UpdateBudgetRequest.budget", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\002", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="update_mask", - full_name="google.cloud.billing.budgets.v1beta1.UpdateBudgetRequest.update_mask", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\001", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=500, - serialized_end=642, -) - - -_GETBUDGETREQUEST = _descriptor.Descriptor( - name="GetBudgetRequest", - full_name="google.cloud.billing.budgets.v1beta1.GetBudgetRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.cloud.billing.budgets.v1beta1.GetBudgetRequest.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=b"".decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\002\372A&\n$billingbudgets.googleapis.com/Budget", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=644, - serialized_end=722, -) - - -_LISTBUDGETSREQUEST = _descriptor.Descriptor( - name="ListBudgetsRequest", - full_name="google.cloud.billing.budgets.v1beta1.ListBudgetsRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name="parent", - full_name="google.cloud.billing.budgets.v1beta1.ListBudgetsRequest.parent", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=b"".decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\002\372A&\022$billingbudgets.googleapis.com/Budget", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="page_size", - full_name="google.cloud.billing.budgets.v1beta1.ListBudgetsRequest.page_size", - index=1, - number=2, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\001", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="page_token", - full_name="google.cloud.billing.budgets.v1beta1.ListBudgetsRequest.page_token", - index=2, - number=3, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=b"".decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\001", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=725, - serialized_end=856, -) - - -_LISTBUDGETSRESPONSE = _descriptor.Descriptor( - name="ListBudgetsResponse", - full_name="google.cloud.billing.budgets.v1beta1.ListBudgetsResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name="budgets", - full_name="google.cloud.billing.budgets.v1beta1.ListBudgetsResponse.budgets", - index=0, - number=1, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - _descriptor.FieldDescriptor( - name="next_page_token", - full_name="google.cloud.billing.budgets.v1beta1.ListBudgetsResponse.next_page_token", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=b"".decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=858, - serialized_end=967, -) - - -_DELETEBUDGETREQUEST = _descriptor.Descriptor( - name="DeleteBudgetRequest", - full_name="google.cloud.billing.budgets.v1beta1.DeleteBudgetRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.cloud.billing.budgets.v1beta1.DeleteBudgetRequest.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=b"".decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=b"\340A\002\372A&\n$billingbudgets.googleapis.com/Budget", - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=969, - serialized_end=1050, -) - -_CREATEBUDGETREQUEST.fields_by_name[ - "budget" -].message_type = ( - google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__model__pb2._BUDGET -) -_UPDATEBUDGETREQUEST.fields_by_name[ - "budget" -].message_type = ( - google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__model__pb2._BUDGET -) -_UPDATEBUDGETREQUEST.fields_by_name[ - "update_mask" -].message_type = google_dot_protobuf_dot_field__mask__pb2._FIELDMASK -_LISTBUDGETSRESPONSE.fields_by_name[ - "budgets" -].message_type = ( - google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__model__pb2._BUDGET -) -DESCRIPTOR.message_types_by_name["CreateBudgetRequest"] = _CREATEBUDGETREQUEST -DESCRIPTOR.message_types_by_name["UpdateBudgetRequest"] = _UPDATEBUDGETREQUEST -DESCRIPTOR.message_types_by_name["GetBudgetRequest"] = _GETBUDGETREQUEST -DESCRIPTOR.message_types_by_name["ListBudgetsRequest"] = _LISTBUDGETSREQUEST -DESCRIPTOR.message_types_by_name["ListBudgetsResponse"] = _LISTBUDGETSRESPONSE -DESCRIPTOR.message_types_by_name["DeleteBudgetRequest"] = _DELETEBUDGETREQUEST -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -CreateBudgetRequest = _reflection.GeneratedProtocolMessageType( - "CreateBudgetRequest", - (_message.Message,), - { - "DESCRIPTOR": _CREATEBUDGETREQUEST, - "__module__": "google.cloud.billing_budgets_v1beta1.proto.budget_service_pb2", - "__doc__": """Request for CreateBudget - - Attributes: - parent: - Required. The name of the billing account to create the budget - in. Values are of the form - ``billingAccounts/{billingAccountId}``. - budget: - Required. Budget to create. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.CreateBudgetRequest) - }, -) -_sym_db.RegisterMessage(CreateBudgetRequest) - -UpdateBudgetRequest = _reflection.GeneratedProtocolMessageType( - "UpdateBudgetRequest", - (_message.Message,), - { - "DESCRIPTOR": _UPDATEBUDGETREQUEST, - "__module__": "google.cloud.billing_budgets_v1beta1.proto.budget_service_pb2", - "__doc__": """Request for UpdateBudget - - Attributes: - budget: - Required. The updated budget object. The budget to update is - specified by the budget name in the budget. - update_mask: - Optional. Indicates which fields in the provided budget to - update. Read-only fields (such as ``name``) cannot be changed. - If this is not provided, then only fields with non-default - values from the request are updated. See - https://developers.google.com/protocol- - buffers/docs/proto3#default for more details about default - values. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.UpdateBudgetRequest) - }, -) -_sym_db.RegisterMessage(UpdateBudgetRequest) - -GetBudgetRequest = _reflection.GeneratedProtocolMessageType( - "GetBudgetRequest", - (_message.Message,), - { - "DESCRIPTOR": _GETBUDGETREQUEST, - "__module__": "google.cloud.billing_budgets_v1beta1.proto.budget_service_pb2", - "__doc__": """Request for GetBudget - - Attributes: - name: - Required. Name of budget to get. Values are of the form - ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.GetBudgetRequest) - }, -) -_sym_db.RegisterMessage(GetBudgetRequest) - -ListBudgetsRequest = _reflection.GeneratedProtocolMessageType( - "ListBudgetsRequest", - (_message.Message,), - { - "DESCRIPTOR": _LISTBUDGETSREQUEST, - "__module__": "google.cloud.billing_budgets_v1beta1.proto.budget_service_pb2", - "__doc__": """Request for ListBudgets - - Attributes: - parent: - Required. Name of billing account to list budgets under. - Values are of the form ``billingAccounts/{billingAccountId}``. - page_size: - Optional. The maximum number of budgets to return per page. - The default and maximum value are 100. - page_token: - Optional. The value returned by the last - ``ListBudgetsResponse`` which indicates that this is a - continuation of a prior ``ListBudgets`` call, and that the - system should return the next page of data. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.ListBudgetsRequest) - }, -) -_sym_db.RegisterMessage(ListBudgetsRequest) - -ListBudgetsResponse = _reflection.GeneratedProtocolMessageType( - "ListBudgetsResponse", - (_message.Message,), - { - "DESCRIPTOR": _LISTBUDGETSRESPONSE, - "__module__": "google.cloud.billing_budgets_v1beta1.proto.budget_service_pb2", - "__doc__": """Response for ListBudgets - - Attributes: - budgets: - List of the budgets owned by the requested billing account. - next_page_token: - If not empty, indicates that there may be more budgets that - match the request; this value should be passed in a new - ``ListBudgetsRequest``. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.ListBudgetsResponse) - }, -) -_sym_db.RegisterMessage(ListBudgetsResponse) - -DeleteBudgetRequest = _reflection.GeneratedProtocolMessageType( - "DeleteBudgetRequest", - (_message.Message,), - { - "DESCRIPTOR": _DELETEBUDGETREQUEST, - "__module__": "google.cloud.billing_budgets_v1beta1.proto.budget_service_pb2", - "__doc__": """Request for DeleteBudget - - Attributes: - name: - Required. Name of the budget to delete. Values are of the form - ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.DeleteBudgetRequest) - }, -) -_sym_db.RegisterMessage(DeleteBudgetRequest) - - -DESCRIPTOR._options = None -_CREATEBUDGETREQUEST.fields_by_name["parent"]._options = None -_CREATEBUDGETREQUEST.fields_by_name["budget"]._options = None -_UPDATEBUDGETREQUEST.fields_by_name["budget"]._options = None -_UPDATEBUDGETREQUEST.fields_by_name["update_mask"]._options = None -_GETBUDGETREQUEST.fields_by_name["name"]._options = None -_LISTBUDGETSREQUEST.fields_by_name["parent"]._options = None -_LISTBUDGETSREQUEST.fields_by_name["page_size"]._options = None -_LISTBUDGETSREQUEST.fields_by_name["page_token"]._options = None -_DELETEBUDGETREQUEST.fields_by_name["name"]._options = None - -_BUDGETSERVICE = _descriptor.ServiceDescriptor( - name="BudgetService", - full_name="google.cloud.billing.budgets.v1beta1.BudgetService", - file=DESCRIPTOR, - index=0, - serialized_options=b"\312A\035billingbudgets.googleapis.com\322A.https://www.googleapis.com/auth/cloud-platform", - create_key=_descriptor._internal_create_key, - serialized_start=1053, - serialized_end=2022, - methods=[ - _descriptor.MethodDescriptor( - name="CreateBudget", - full_name="google.cloud.billing.budgets.v1beta1.BudgetService.CreateBudget", - index=0, - containing_service=None, - input_type=_CREATEBUDGETREQUEST, - output_type=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__model__pb2._BUDGET, - serialized_options=b'\202\323\344\223\0020"+/v1beta1/{parent=billingAccounts/*}/budgets:\001*', - create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name="UpdateBudget", - full_name="google.cloud.billing.budgets.v1beta1.BudgetService.UpdateBudget", - index=1, - containing_service=None, - input_type=_UPDATEBUDGETREQUEST, - output_type=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__model__pb2._BUDGET, - serialized_options=b"\202\323\344\223\002722/v1beta1/{budget.name=billingAccounts/*/budgets/*}:\001*", - create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name="GetBudget", - full_name="google.cloud.billing.budgets.v1beta1.BudgetService.GetBudget", - index=2, - containing_service=None, - input_type=_GETBUDGETREQUEST, - output_type=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__model__pb2._BUDGET, - serialized_options=b"\202\323\344\223\002-\022+/v1beta1/{name=billingAccounts/*/budgets/*}", - create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name="ListBudgets", - full_name="google.cloud.billing.budgets.v1beta1.BudgetService.ListBudgets", - index=3, - containing_service=None, - input_type=_LISTBUDGETSREQUEST, - output_type=_LISTBUDGETSRESPONSE, - serialized_options=b"\202\323\344\223\002-\022+/v1beta1/{parent=billingAccounts/*}/budgets", - create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name="DeleteBudget", - full_name="google.cloud.billing.budgets.v1beta1.BudgetService.DeleteBudget", - index=4, - containing_service=None, - input_type=_DELETEBUDGETREQUEST, - output_type=google_dot_protobuf_dot_empty__pb2._EMPTY, - serialized_options=b"\202\323\344\223\002-*+/v1beta1/{name=billingAccounts/*/budgets/*}", - create_key=_descriptor._internal_create_key, - ), - ], -) -_sym_db.RegisterServiceDescriptor(_BUDGETSERVICE) - -DESCRIPTOR.services_by_name["BudgetService"] = _BUDGETSERVICE - -# @@protoc_insertion_point(module_scope) diff --git a/google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2_grpc.py b/google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2_grpc.py deleted file mode 100644 index fbd9c92..0000000 --- a/google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2_grpc.py +++ /dev/null @@ -1,139 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc - -from google.cloud.billing_budgets_v1beta1.proto import ( - budget_model_pb2 as google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__model__pb2, -) -from google.cloud.billing_budgets_v1beta1.proto import ( - budget_service_pb2 as google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__service__pb2, -) -from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 - - -class BudgetServiceStub(object): - """BudgetService stores Cloud Billing budgets, which define a - budget plan and rules to execute as we track spend against that plan. - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.CreateBudget = channel.unary_unary( - "/google.cloud.billing.budgets.v1beta1.BudgetService/CreateBudget", - request_serializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__service__pb2.CreateBudgetRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__model__pb2.Budget.FromString, - ) - self.UpdateBudget = channel.unary_unary( - "/google.cloud.billing.budgets.v1beta1.BudgetService/UpdateBudget", - request_serializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__service__pb2.UpdateBudgetRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__model__pb2.Budget.FromString, - ) - self.GetBudget = channel.unary_unary( - "/google.cloud.billing.budgets.v1beta1.BudgetService/GetBudget", - request_serializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__service__pb2.GetBudgetRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__model__pb2.Budget.FromString, - ) - self.ListBudgets = channel.unary_unary( - "/google.cloud.billing.budgets.v1beta1.BudgetService/ListBudgets", - request_serializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__service__pb2.ListBudgetsRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__service__pb2.ListBudgetsResponse.FromString, - ) - self.DeleteBudget = channel.unary_unary( - "/google.cloud.billing.budgets.v1beta1.BudgetService/DeleteBudget", - request_serializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__service__pb2.DeleteBudgetRequest.SerializeToString, - response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString, - ) - - -class BudgetServiceServicer(object): - """BudgetService stores Cloud Billing budgets, which define a - budget plan and rules to execute as we track spend against that plan. - """ - - def CreateBudget(self, request, context): - """Creates a new budget. See - Quotas and limits - for more information on the limits of the number of budgets you can create. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def UpdateBudget(self, request, context): - """Updates a budget and returns the updated budget. - - WARNING: There are some fields exposed on the Google Cloud Console that - aren't available on this API. Budget fields that are not exposed in - this API will not be changed by this method. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def GetBudget(self, request, context): - """Returns a budget. - - WARNING: There are some fields exposed on the Google Cloud Console that - aren't available on this API. When reading from the API, you will not - see these fields in the return value, though they may have been set - in the Cloud Console. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def ListBudgets(self, request, context): - """Returns a list of budgets for a billing account. - - WARNING: There are some fields exposed on the Google Cloud Console that - aren't available on this API. When reading from the API, you will not - see these fields in the return value, though they may have been set - in the Cloud Console. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def DeleteBudget(self, request, context): - """Deletes a budget. Returns successfully if already deleted. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - -def add_BudgetServiceServicer_to_server(servicer, server): - rpc_method_handlers = { - "CreateBudget": grpc.unary_unary_rpc_method_handler( - servicer.CreateBudget, - request_deserializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__service__pb2.CreateBudgetRequest.FromString, - response_serializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__model__pb2.Budget.SerializeToString, - ), - "UpdateBudget": grpc.unary_unary_rpc_method_handler( - servicer.UpdateBudget, - request_deserializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__service__pb2.UpdateBudgetRequest.FromString, - response_serializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__model__pb2.Budget.SerializeToString, - ), - "GetBudget": grpc.unary_unary_rpc_method_handler( - servicer.GetBudget, - request_deserializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__service__pb2.GetBudgetRequest.FromString, - response_serializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__model__pb2.Budget.SerializeToString, - ), - "ListBudgets": grpc.unary_unary_rpc_method_handler( - servicer.ListBudgets, - request_deserializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__service__pb2.ListBudgetsRequest.FromString, - response_serializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__service__pb2.ListBudgetsResponse.SerializeToString, - ), - "DeleteBudget": grpc.unary_unary_rpc_method_handler( - servicer.DeleteBudget, - request_deserializer=google_dot_cloud_dot_billing__budgets__v1beta1_dot_proto_dot_budget__service__pb2.DeleteBudgetRequest.FromString, - response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - "google.cloud.billing.budgets.v1beta1.BudgetService", rpc_method_handlers - ) - server.add_generic_rpc_handlers((generic_handler,)) diff --git a/google/cloud/billing_budgets_v1beta1/types.py b/google/cloud/billing_budgets_v1beta1/types.py deleted file mode 100644 index 0d1ee0b..0000000 --- a/google/cloud/billing_budgets_v1beta1/types.py +++ /dev/null @@ -1,56 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# 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. - - -from __future__ import absolute_import -import sys - -from google.api_core.protobuf_helpers import get_messages - -from google.cloud.billing_budgets_v1beta1.proto import budget_model_pb2 -from google.cloud.billing_budgets_v1beta1.proto import budget_service_pb2 -from google.protobuf import empty_pb2 -from google.protobuf import field_mask_pb2 -from google.protobuf import struct_pb2 -from google.type import money_pb2 - - -_shared_modules = [ - empty_pb2, - field_mask_pb2, - struct_pb2, - money_pb2, -] - -_local_modules = [ - budget_model_pb2, - budget_service_pb2, -] - -names = [] - -for module in _shared_modules: # pragma: NO COVER - for name, message in get_messages(module).items(): - setattr(sys.modules[__name__], name, message) - names.append(name) -for module in _local_modules: - for name, message in get_messages(module).items(): - message.__module__ = "google.cloud.billing_budgets_v1beta1.types" - setattr(sys.modules[__name__], name, message) - names.append(name) - - -__all__ = tuple(sorted(names)) diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 0000000..4505b48 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,3 @@ +[mypy] +python_version = 3.6 +namespace_packages = True diff --git a/noxfile.py b/noxfile.py index b6bb282..18abaac 100644 --- a/noxfile.py +++ b/noxfile.py @@ -27,8 +27,8 @@ BLACK_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"] DEFAULT_PYTHON_VERSION = "3.8" -SYSTEM_TEST_PYTHON_VERSIONS = ["2.7", "3.8"] -UNIT_TEST_PYTHON_VERSIONS = ["2.7", "3.5", "3.6", "3.7", "3.8"] +SYSTEM_TEST_PYTHON_VERSIONS = ["3.8"] +UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8"] @nox.session(python=DEFAULT_PYTHON_VERSION) @@ -70,6 +70,8 @@ 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") session.install("-e", ".") @@ -77,7 +79,7 @@ def default(session): session.run( "py.test", "--quiet", - "--cov=google.cloud.billingbudgets", + "--cov=google.cloud.billing.budgets", "--cov=google.cloud", "--cov=tests.unit", "--cov-append", @@ -135,7 +137,7 @@ def cover(session): test runs (not system test runs), and then erases coverage data. """ session.install("coverage", "pytest-cov") - session.run("coverage", "report", "--show-missing", "--fail-under=70") + session.run("coverage", "report", "--show-missing", "--fail-under=99") session.run("coverage", "erase") diff --git a/samples/AUTHORING_GUIDE.md b/samples/AUTHORING_GUIDE.md new file mode 100644 index 0000000..55c97b3 --- /dev/null +++ b/samples/AUTHORING_GUIDE.md @@ -0,0 +1 @@ +See https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/AUTHORING_GUIDE.md \ No newline at end of file diff --git a/samples/CONTRIBUTING.md b/samples/CONTRIBUTING.md new file mode 100644 index 0000000..34c882b --- /dev/null +++ b/samples/CONTRIBUTING.md @@ -0,0 +1 @@ +See https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/CONTRIBUTING.md \ No newline at end of file diff --git a/scripts/fixup_budgets_v1beta1_keywords.py b/scripts/fixup_budgets_v1beta1_keywords.py new file mode 100644 index 0000000..68c6999 --- /dev/null +++ b/scripts/fixup_budgets_v1beta1_keywords.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- + +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import argparse +import os +import libcst as cst +import pathlib +import sys +from typing import (Any, Callable, Dict, List, Sequence, Tuple) + + +def partition( + predicate: Callable[[Any], bool], + iterator: Sequence[Any] +) -> Tuple[List[Any], List[Any]]: + """A stable, out-of-place partition.""" + results = ([], []) + + for i in iterator: + results[int(predicate(i))].append(i) + + # Returns trueList, falseList + return results[1], results[0] + + +class budgetsCallTransformer(cst.CSTTransformer): + CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') + METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { + 'create_budget': ('parent', 'budget', ), + 'delete_budget': ('name', ), + 'get_budget': ('name', ), + 'list_budgets': ('parent', 'page_size', 'page_token', ), + 'update_budget': ('budget', 'update_mask', ), + } + + def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: + try: + key = original.func.attr.value + kword_params = self.METHOD_TO_PARAMS[key] + except (AttributeError, KeyError): + # Either not a method from the API or too convoluted to be sure. + return updated + + # If the existing code is valid, keyword args come after positional args. + # Therefore, all positional args must map to the first parameters. + args, kwargs = partition(lambda a: not bool(a.keyword), updated.args) + if any(k.keyword.value == "request" for k in kwargs): + # We've already fixed this file, don't fix it again. + return updated + + kwargs, ctrl_kwargs = partition( + lambda a: not a.keyword.value in self.CTRL_PARAMS, + kwargs + ) + + args, ctrl_args = args[:len(kword_params)], args[len(kword_params):] + ctrl_kwargs.extend(cst.Arg(value=a.value, keyword=cst.Name(value=ctrl)) + for a, ctrl in zip(ctrl_args, self.CTRL_PARAMS)) + + request_arg = cst.Arg( + value=cst.Dict([ + cst.DictElement( + cst.SimpleString("'{}'".format(name)), + cst.Element(value=arg.value) + ) + # Note: the args + kwargs looks silly, but keep in mind that + # the control parameters had to be stripped out, and that + # those could have been passed positionally or by keyword. + for name, arg in zip(kword_params, args + kwargs)]), + keyword=cst.Name("request") + ) + + return updated.with_changes( + args=[request_arg] + ctrl_kwargs + ) + + +def fix_files( + in_dir: pathlib.Path, + out_dir: pathlib.Path, + *, + transformer=budgetsCallTransformer(), +): + """Duplicate the input dir to the output dir, fixing file method calls. + + Preconditions: + * in_dir is a real directory + * out_dir is a real, empty directory + """ + pyfile_gen = ( + pathlib.Path(os.path.join(root, f)) + for root, _, files in os.walk(in_dir) + for f in files if os.path.splitext(f)[1] == ".py" + ) + + for fpath in pyfile_gen: + with open(fpath, 'r') as f: + src = f.read() + + # Parse the code and insert method call fixes. + tree = cst.parse_module(src) + updated = tree.visit(transformer) + + # Create the path and directory structure for the new file. + updated_path = out_dir.joinpath(fpath.relative_to(in_dir)) + updated_path.parent.mkdir(parents=True, exist_ok=True) + + # Generate the updated source file at the corresponding path. + with open(updated_path, 'w') as f: + f.write(updated.code) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description="""Fix up source that uses the budgets client library. + +The existing sources are NOT overwritten but are copied to output_dir with changes made. + +Note: This tool operates at a best-effort level at converting positional + parameters in client method calls to keyword based parameters. + Cases where it WILL FAIL include + A) * or ** expansion in a method call. + B) Calls via function or method alias (includes free function calls) + C) Indirect or dispatched calls (e.g. the method is looked up dynamically) + + These all constitute false negatives. The tool will also detect false + positives when an API method shares a name with another method. +""") + parser.add_argument( + '-d', + '--input-directory', + required=True, + dest='input_dir', + help='the input directory to walk for python files to fix up', + ) + parser.add_argument( + '-o', + '--output-directory', + required=True, + dest='output_dir', + help='the directory to output files fixed via un-flattening', + ) + args = parser.parse_args() + input_dir = pathlib.Path(args.input_dir) + output_dir = pathlib.Path(args.output_dir) + if not input_dir.is_dir(): + print( + f"input directory '{input_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if not output_dir.is_dir(): + print( + f"output directory '{output_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if os.listdir(output_dir): + print( + f"output directory '{output_dir}' is not empty", + file=sys.stderr, + ) + sys.exit(-1) + + fix_files(input_dir, output_dir) diff --git a/setup.py b/setup.py index 215796a..ef83bc4 100644 --- a/setup.py +++ b/setup.py @@ -25,8 +25,9 @@ version = "0.4.0" release_status = "Development Status :: 4 - Beta" dependencies = [ - "google-api-core[grpc] >= 1.14.0, < 2.0.0dev", - 'enum34; python_version < "3.4"', + "google-api-core[grpc] >= 1.21.0, < 2.0.0dev", + "proto-plus >= 0.4.0", + "libcst >= 0.2.5", ] @@ -37,7 +38,9 @@ readme = readme_file.read() packages = [ - package for package in setuptools.find_packages() if package.startswith("google") + package + for package in setuptools.PEP420PackageFinder.find() + if package.startswith("google") ] namespaces = ["google"] @@ -60,14 +63,16 @@ "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Operating System :: OS Independent", "Topic :: Internet", ], platforms="Posix; MacOS X; Windows", packages=packages, + python_requires=">=3.6", + scripts=["scripts/fixup_budgets_v1beta1_keywords.py"], namespace_packages=namespaces, install_requires=dependencies, include_package_data=True, diff --git a/synth.metadata b/synth.metadata index b32982f..205947a 100644 --- a/synth.metadata +++ b/synth.metadata @@ -4,22 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/python-billingbudgets.git", - "sha": "2fc26490d54ed4bc5c2c074188533593fa863bb5" - } - }, - { - "git": { - "name": "googleapis", - "remote": "https://github.com/googleapis/googleapis.git", - "sha": "cf41866c6f14f10a07aa1e2a1260fc0a2727d889", - "internalRef": "317812187" + "sha": "d2165d55e63ebb803bf18b9597e17bee8792f8a1" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "303271797a360f8a439203413f13a160f2f5b3b4" + "sha": "d82deccf657a66e31bd5da9efdb96c6fa322fc7e" } } ], diff --git a/synth.py b/synth.py index f9c9096..558a3a8 100644 --- a/synth.py +++ b/synth.py @@ -31,6 +31,7 @@ version="v1beta1", bazel_target="//google/cloud/billing/budgets/v1beta1:billing-budgets-v1beta1-py", include_protos=True, + proto_output_path=f"google/cloud/billing/budgets_v1beta1/proto" ) excludes = [ @@ -42,28 +43,24 @@ s.move(library, excludes=excludes) -# Fix namespace -s.replace( - "**/*.py", - "from google\.cloud\.billing\.budgets_v1beta1", - "from google.cloud.billing_budgets_v1beta1", -) - -# Fix package name -s.replace( - ["**/*.rst", "setup.py", "*/**/*.py"], - "google-cloud-billingbudgets", - "google-cloud-billing-budgets", -) - # ---------------------------------------------------------------------------- # Add templated files # ---------------------------------------------------------------------------- -templated_files = common.py_library(cov_level=70) -s.move(templated_files) +templated_files = common.py_library( + samples=False, # set to True only if there are samples + microgenerator=True, + cov_level=99, +) +s.move(templated_files, excludes=[".coveragerc"]) # microgenerator has a good .coveragerc file # TODO(busunkim): Use latest sphinx after microgenerator transition s.replace("noxfile.py", """['"]sphinx['"]""", '"sphinx<3.0.0"') +# Update the namespace in noxfile.py +s.replace( + "noxfile.py", + "google.cloud.billingbudgets", + "google.cloud.billing.budgets" +) s.shell.run(["nox", "-s", "blacken"], hide_output=False) diff --git a/tests/unit/gapic/budgets_v1beta1/test_budget_service.py b/tests/unit/gapic/budgets_v1beta1/test_budget_service.py new file mode 100644 index 0000000..14953e2 --- /dev/null +++ b/tests/unit/gapic/budgets_v1beta1/test_budget_service.py @@ -0,0 +1,1392 @@ +# -*- coding: utf-8 -*- + +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import os +import mock + +import grpc +from grpc.experimental import aio +import math +import pytest + +from google import auth +from google.api_core import client_options +from google.api_core import exceptions +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers +from google.api_core import grpc_helpers_async +from google.auth import credentials +from google.auth.exceptions import MutualTLSChannelError +from google.cloud.billing.budgets_v1beta1.services.budget_service import ( + BudgetServiceAsyncClient, +) +from google.cloud.billing.budgets_v1beta1.services.budget_service import ( + BudgetServiceClient, +) +from google.cloud.billing.budgets_v1beta1.services.budget_service import pagers +from google.cloud.billing.budgets_v1beta1.services.budget_service import transports +from google.cloud.billing.budgets_v1beta1.types import budget_model +from google.cloud.billing.budgets_v1beta1.types import budget_service +from google.oauth2 import service_account +from google.protobuf import field_mask_pb2 as field_mask # type: ignore +from google.protobuf import struct_pb2 as struct # type: ignore +from google.type import money_pb2 as money # type: ignore + + +def client_cert_source_callback(): + return b"cert bytes", b"key bytes" + + +def test__get_default_mtls_endpoint(): + api_endpoint = "example.googleapis.com" + api_mtls_endpoint = "example.mtls.googleapis.com" + sandbox_endpoint = "example.sandbox.googleapis.com" + sandbox_mtls_endpoint = "example.mtls.sandbox.googleapis.com" + non_googleapi = "api.example.com" + + assert BudgetServiceClient._get_default_mtls_endpoint(None) is None + assert ( + BudgetServiceClient._get_default_mtls_endpoint(api_endpoint) + == api_mtls_endpoint + ) + assert ( + BudgetServiceClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + BudgetServiceClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + BudgetServiceClient._get_default_mtls_endpoint(sandbox_mtls_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + BudgetServiceClient._get_default_mtls_endpoint(non_googleapi) == non_googleapi + ) + + +@pytest.mark.parametrize( + "client_class", [BudgetServiceClient, BudgetServiceAsyncClient] +) +def test_budget_service_client_from_service_account_file(client_class): + creds = credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_file" + ) as factory: + factory.return_value = creds + client = client_class.from_service_account_file("dummy/file/path.json") + assert client._transport._credentials == creds + + client = client_class.from_service_account_json("dummy/file/path.json") + assert client._transport._credentials == creds + + assert client._transport._host == "billingbudgets.googleapis.com:443" + + +def test_budget_service_client_get_transport_class(): + transport = BudgetServiceClient.get_transport_class() + assert transport == transports.BudgetServiceGrpcTransport + + transport = BudgetServiceClient.get_transport_class("grpc") + assert transport == transports.BudgetServiceGrpcTransport + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (BudgetServiceClient, transports.BudgetServiceGrpcTransport, "grpc"), + ( + BudgetServiceAsyncClient, + transports.BudgetServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ], +) +def test_budget_service_client_client_options( + client_class, transport_class, transport_name +): + # Check that if channel is provided we won't create a new one. + with mock.patch.object(BudgetServiceClient, "get_transport_class") as gtc: + transport = transport_class(credentials=credentials.AnonymousCredentials()) + client = client_class(transport=transport) + gtc.assert_not_called() + + # Check that if channel is provided via str we will create a new one. + with mock.patch.object(BudgetServiceClient, "get_transport_class") as gtc: + client = client_class(transport=transport_name) + gtc.assert_called() + + # Check the case api_endpoint is provided. + options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + api_mtls_endpoint="squid.clam.whelk", + client_cert_source=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # "never". + os.environ["GOOGLE_API_USE_MTLS"] = "never" + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class() + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + api_mtls_endpoint=client.DEFAULT_ENDPOINT, + client_cert_source=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # "always". + os.environ["GOOGLE_API_USE_MTLS"] = "always" + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class() + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_MTLS_ENDPOINT, + scopes=None, + api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, + client_cert_source=None, + ) + + # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is + # "auto", and client_cert_source is provided. + os.environ["GOOGLE_API_USE_MTLS"] = "auto" + options = client_options.ClientOptions( + client_cert_source=client_cert_source_callback + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_MTLS_ENDPOINT, + scopes=None, + api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, + client_cert_source=client_cert_source_callback, + ) + + # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is + # "auto", and default_client_cert_source is provided. + os.environ["GOOGLE_API_USE_MTLS"] = "auto" + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, + ): + patched.return_value = None + client = client_class() + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_MTLS_ENDPOINT, + scopes=None, + api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, + client_cert_source=None, + ) + + # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is + # "auto", but client_cert_source and default_client_cert_source are None. + os.environ["GOOGLE_API_USE_MTLS"] = "auto" + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + patched.return_value = None + client = client_class() + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + api_mtls_endpoint=client.DEFAULT_ENDPOINT, + client_cert_source=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS has + # unsupported value. + os.environ["GOOGLE_API_USE_MTLS"] = "Unsupported" + with pytest.raises(MutualTLSChannelError): + client = client_class() + + del os.environ["GOOGLE_API_USE_MTLS"] + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (BudgetServiceClient, transports.BudgetServiceGrpcTransport, "grpc"), + ( + BudgetServiceAsyncClient, + transports.BudgetServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ], +) +def test_budget_service_client_client_options_scopes( + client_class, transport_class, transport_name +): + # Check the case scopes are provided. + options = client_options.ClientOptions(scopes=["1", "2"],) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=["1", "2"], + api_mtls_endpoint=client.DEFAULT_ENDPOINT, + client_cert_source=None, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (BudgetServiceClient, transports.BudgetServiceGrpcTransport, "grpc"), + ( + BudgetServiceAsyncClient, + transports.BudgetServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ], +) +def test_budget_service_client_client_options_credentials_file( + client_class, transport_class, transport_name +): + # Check the case credentials file is provided. + options = client_options.ClientOptions(credentials_file="credentials.json") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file="credentials.json", + host=client.DEFAULT_ENDPOINT, + scopes=None, + api_mtls_endpoint=client.DEFAULT_ENDPOINT, + client_cert_source=None, + ) + + +def test_budget_service_client_client_options_from_dict(): + with mock.patch( + "google.cloud.billing.budgets_v1beta1.services.budget_service.transports.BudgetServiceGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = BudgetServiceClient( + client_options={"api_endpoint": "squid.clam.whelk"} + ) + grpc_transport.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + api_mtls_endpoint="squid.clam.whelk", + client_cert_source=None, + ) + + +def test_create_budget(transport: str = "grpc"): + client = BudgetServiceClient( + credentials=credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = budget_service.CreateBudgetRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.create_budget), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = budget_model.Budget( + name="name_value", display_name="display_name_value", etag="etag_value", + ) + + response = client.create_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, budget_model.Budget) + + assert response.name == "name_value" + + assert response.display_name == "display_name_value" + + assert response.etag == "etag_value" + + +@pytest.mark.asyncio +async def test_create_budget_async(transport: str = "grpc_asyncio"): + client = BudgetServiceAsyncClient( + credentials=credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = budget_service.CreateBudgetRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._client._transport.create_budget), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + budget_model.Budget( + name="name_value", display_name="display_name_value", etag="etag_value", + ) + ) + + response = await client.create_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, budget_model.Budget) + + assert response.name == "name_value" + + assert response.display_name == "display_name_value" + + assert response.etag == "etag_value" + + +def test_create_budget_field_headers(): + client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = budget_service.CreateBudgetRequest() + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.create_budget), "__call__") as call: + call.return_value = budget_model.Budget() + + client.create_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_create_budget_field_headers_async(): + client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = budget_service.CreateBudgetRequest() + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._client._transport.create_budget), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(budget_model.Budget()) + + await client.create_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"] + + +def test_update_budget(transport: str = "grpc"): + client = BudgetServiceClient( + credentials=credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = budget_service.UpdateBudgetRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.update_budget), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = budget_model.Budget( + name="name_value", display_name="display_name_value", etag="etag_value", + ) + + response = client.update_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, budget_model.Budget) + + assert response.name == "name_value" + + assert response.display_name == "display_name_value" + + assert response.etag == "etag_value" + + +@pytest.mark.asyncio +async def test_update_budget_async(transport: str = "grpc_asyncio"): + client = BudgetServiceAsyncClient( + credentials=credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = budget_service.UpdateBudgetRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._client._transport.update_budget), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + budget_model.Budget( + name="name_value", display_name="display_name_value", etag="etag_value", + ) + ) + + response = await client.update_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, budget_model.Budget) + + assert response.name == "name_value" + + assert response.display_name == "display_name_value" + + assert response.etag == "etag_value" + + +def test_update_budget_field_headers(): + client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = budget_service.UpdateBudgetRequest() + request.budget.name = "budget.name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.update_budget), "__call__") as call: + call.return_value = budget_model.Budget() + + client.update_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "budget.name=budget.name/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_update_budget_field_headers_async(): + client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = budget_service.UpdateBudgetRequest() + request.budget.name = "budget.name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._client._transport.update_budget), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(budget_model.Budget()) + + await client.update_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "budget.name=budget.name/value",) in kw["metadata"] + + +def test_get_budget(transport: str = "grpc"): + client = BudgetServiceClient( + credentials=credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = budget_service.GetBudgetRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.get_budget), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = budget_model.Budget( + name="name_value", display_name="display_name_value", etag="etag_value", + ) + + response = client.get_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, budget_model.Budget) + + assert response.name == "name_value" + + assert response.display_name == "display_name_value" + + assert response.etag == "etag_value" + + +@pytest.mark.asyncio +async def test_get_budget_async(transport: str = "grpc_asyncio"): + client = BudgetServiceAsyncClient( + credentials=credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = budget_service.GetBudgetRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._client._transport.get_budget), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + budget_model.Budget( + name="name_value", display_name="display_name_value", etag="etag_value", + ) + ) + + response = await client.get_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, budget_model.Budget) + + assert response.name == "name_value" + + assert response.display_name == "display_name_value" + + assert response.etag == "etag_value" + + +def test_get_budget_field_headers(): + client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = budget_service.GetBudgetRequest() + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.get_budget), "__call__") as call: + call.return_value = budget_model.Budget() + + client.get_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_budget_field_headers_async(): + client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = budget_service.GetBudgetRequest() + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._client._transport.get_budget), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(budget_model.Budget()) + + await client.get_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +def test_list_budgets(transport: str = "grpc"): + client = BudgetServiceClient( + credentials=credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = budget_service.ListBudgetsRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.list_budgets), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = budget_service.ListBudgetsResponse( + next_page_token="next_page_token_value", + ) + + response = client.list_budgets(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListBudgetsPager) + + assert response.next_page_token == "next_page_token_value" + + +@pytest.mark.asyncio +async def test_list_budgets_async(transport: str = "grpc_asyncio"): + client = BudgetServiceAsyncClient( + credentials=credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = budget_service.ListBudgetsRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._client._transport.list_budgets), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + budget_service.ListBudgetsResponse(next_page_token="next_page_token_value",) + ) + + response = await client.list_budgets(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListBudgetsAsyncPager) + + assert response.next_page_token == "next_page_token_value" + + +def test_list_budgets_field_headers(): + client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = budget_service.ListBudgetsRequest() + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.list_budgets), "__call__") as call: + call.return_value = budget_service.ListBudgetsResponse() + + client.list_budgets(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_list_budgets_field_headers_async(): + client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = budget_service.ListBudgetsRequest() + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._client._transport.list_budgets), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + budget_service.ListBudgetsResponse() + ) + + await client.list_budgets(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"] + + +def test_list_budgets_pager(): + client = BudgetServiceClient(credentials=credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.list_budgets), "__call__") as call: + # Set the response to a series of pages. + call.side_effect = ( + budget_service.ListBudgetsResponse( + budgets=[ + budget_model.Budget(), + budget_model.Budget(), + budget_model.Budget(), + ], + next_page_token="abc", + ), + budget_service.ListBudgetsResponse(budgets=[], next_page_token="def",), + budget_service.ListBudgetsResponse( + budgets=[budget_model.Budget(),], next_page_token="ghi", + ), + budget_service.ListBudgetsResponse( + budgets=[budget_model.Budget(), budget_model.Budget(),], + ), + RuntimeError, + ) + + metadata = () + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", ""),)), + ) + pager = client.list_budgets(request={}) + + assert pager._metadata == metadata + + results = [i for i in pager] + assert len(results) == 6 + assert all(isinstance(i, budget_model.Budget) for i in results) + + +def test_list_budgets_pages(): + client = BudgetServiceClient(credentials=credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.list_budgets), "__call__") as call: + # Set the response to a series of pages. + call.side_effect = ( + budget_service.ListBudgetsResponse( + budgets=[ + budget_model.Budget(), + budget_model.Budget(), + budget_model.Budget(), + ], + next_page_token="abc", + ), + budget_service.ListBudgetsResponse(budgets=[], next_page_token="def",), + budget_service.ListBudgetsResponse( + budgets=[budget_model.Budget(),], next_page_token="ghi", + ), + budget_service.ListBudgetsResponse( + budgets=[budget_model.Budget(), budget_model.Budget(),], + ), + RuntimeError, + ) + pages = list(client.list_budgets(request={}).pages) + for page, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page.raw_page.next_page_token == token + + +@pytest.mark.asyncio +async def test_list_budgets_async_pager(): + client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._client._transport.list_budgets), + "__call__", + new_callable=mock.AsyncMock, + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + budget_service.ListBudgetsResponse( + budgets=[ + budget_model.Budget(), + budget_model.Budget(), + budget_model.Budget(), + ], + next_page_token="abc", + ), + budget_service.ListBudgetsResponse(budgets=[], next_page_token="def",), + budget_service.ListBudgetsResponse( + budgets=[budget_model.Budget(),], next_page_token="ghi", + ), + budget_service.ListBudgetsResponse( + budgets=[budget_model.Budget(), budget_model.Budget(),], + ), + RuntimeError, + ) + async_pager = await client.list_budgets(request={},) + assert async_pager.next_page_token == "abc" + responses = [] + async for response in async_pager: + responses.append(response) + + assert len(responses) == 6 + assert all(isinstance(i, budget_model.Budget) for i in responses) + + +@pytest.mark.asyncio +async def test_list_budgets_async_pages(): + client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._client._transport.list_budgets), + "__call__", + new_callable=mock.AsyncMock, + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + budget_service.ListBudgetsResponse( + budgets=[ + budget_model.Budget(), + budget_model.Budget(), + budget_model.Budget(), + ], + next_page_token="abc", + ), + budget_service.ListBudgetsResponse(budgets=[], next_page_token="def",), + budget_service.ListBudgetsResponse( + budgets=[budget_model.Budget(),], next_page_token="ghi", + ), + budget_service.ListBudgetsResponse( + budgets=[budget_model.Budget(), budget_model.Budget(),], + ), + RuntimeError, + ) + pages = [] + async for page in (await client.list_budgets(request={})).pages: + pages.append(page) + for page, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page.raw_page.next_page_token == token + + +def test_delete_budget(transport: str = "grpc"): + client = BudgetServiceClient( + credentials=credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = budget_service.DeleteBudgetRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.delete_budget), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = None + + response = client.delete_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + + assert args[0] == request + + # Establish that the response is the type that we expect. + assert response is None + + +@pytest.mark.asyncio +async def test_delete_budget_async(transport: str = "grpc_asyncio"): + client = BudgetServiceAsyncClient( + credentials=credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = budget_service.DeleteBudgetRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._client._transport.delete_budget), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + + response = await client.delete_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + + assert args[0] == request + + # Establish that the response is the type that we expect. + assert response is None + + +def test_delete_budget_field_headers(): + client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = budget_service.DeleteBudgetRequest() + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.delete_budget), "__call__") as call: + call.return_value = None + + client.delete_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_delete_budget_field_headers_async(): + client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = budget_service.DeleteBudgetRequest() + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._client._transport.delete_budget), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + + await client.delete_budget(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.BudgetServiceGrpcTransport( + credentials=credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = BudgetServiceClient( + credentials=credentials.AnonymousCredentials(), transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.BudgetServiceGrpcTransport( + credentials=credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = BudgetServiceClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.BudgetServiceGrpcTransport( + credentials=credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = BudgetServiceClient( + client_options={"scopes": ["1", "2"]}, transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.BudgetServiceGrpcTransport( + credentials=credentials.AnonymousCredentials(), + ) + client = BudgetServiceClient(transport=transport) + assert client._transport is transport + + +def test_transport_get_channel(): + # A client may be instantiated with a custom transport instance. + transport = transports.BudgetServiceGrpcTransport( + credentials=credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + transport = transports.BudgetServiceGrpcAsyncIOTransport( + credentials=credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + +def test_transport_grpc_default(): + # A client should use the gRPC transport by default. + client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + assert isinstance(client._transport, transports.BudgetServiceGrpcTransport,) + + +def test_budget_service_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(exceptions.DuplicateCredentialArgs): + transport = transports.BudgetServiceTransport( + credentials=credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_budget_service_base_transport(): + # Instantiate the base transport. + transport = transports.BudgetServiceTransport( + credentials=credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ( + "create_budget", + "update_budget", + "get_budget", + "list_budgets", + "delete_budget", + ) + for method in methods: + with pytest.raises(NotImplementedError): + getattr(transport, method)(request=object()) + + +def test_budget_service_base_transport_with_credentials_file(): + # Instantiate the base transport with a credentials file + with mock.patch.object(auth, "load_credentials_from_file") as load_creds: + load_creds.return_value = (credentials.AnonymousCredentials(), None) + transport = transports.BudgetServiceTransport( + credentials_file="credentials.json", + ) + load_creds.assert_called_once_with( + "credentials.json", + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ) + + +def test_budget_service_auth_adc(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(auth, "default") as adc: + adc.return_value = (credentials.AnonymousCredentials(), None) + BudgetServiceClient() + adc.assert_called_once_with( + scopes=("https://www.googleapis.com/auth/cloud-platform",) + ) + + +def test_budget_service_transport_auth_adc(): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object(auth, "default") as adc: + adc.return_value = (credentials.AnonymousCredentials(), None) + transports.BudgetServiceGrpcTransport(host="squid.clam.whelk") + adc.assert_called_once_with( + scopes=("https://www.googleapis.com/auth/cloud-platform",) + ) + + +def test_budget_service_host_no_port(): + client = BudgetServiceClient( + credentials=credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="billingbudgets.googleapis.com" + ), + ) + assert client._transport._host == "billingbudgets.googleapis.com:443" + + +def test_budget_service_host_with_port(): + client = BudgetServiceClient( + credentials=credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="billingbudgets.googleapis.com:8000" + ), + ) + assert client._transport._host == "billingbudgets.googleapis.com:8000" + + +def test_budget_service_grpc_transport_channel(): + channel = grpc.insecure_channel("http://localhost/") + + # Check that if channel is provided, mtls endpoint and client_cert_source + # won't be used. + callback = mock.MagicMock() + transport = transports.BudgetServiceGrpcTransport( + host="squid.clam.whelk", + channel=channel, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=callback, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert not callback.called + + +def test_budget_service_grpc_asyncio_transport_channel(): + channel = aio.insecure_channel("http://localhost/") + + # Check that if channel is provided, mtls endpoint and client_cert_source + # won't be used. + callback = mock.MagicMock() + transport = transports.BudgetServiceGrpcAsyncIOTransport( + host="squid.clam.whelk", + channel=channel, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=callback, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert not callback.called + + +@mock.patch("grpc.ssl_channel_credentials", autospec=True) +@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) +def test_budget_service_grpc_transport_channel_mtls_with_client_cert_source( + grpc_create_channel, grpc_ssl_channel_cred +): + # Check that if channel is None, but api_mtls_endpoint and client_cert_source + # are provided, then a mTLS channel will be created. + mock_cred = mock.Mock() + + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + transport = transports.BudgetServiceGrpcTransport( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + ) + assert transport.grpc_channel == mock_grpc_channel + + +@mock.patch("grpc.ssl_channel_credentials", autospec=True) +@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) +def test_budget_service_grpc_asyncio_transport_channel_mtls_with_client_cert_source( + grpc_create_channel, grpc_ssl_channel_cred +): + # Check that if channel is None, but api_mtls_endpoint and client_cert_source + # are provided, then a mTLS channel will be created. + mock_cred = mock.Mock() + + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + transport = transports.BudgetServiceGrpcAsyncIOTransport( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + ) + assert transport.grpc_channel == mock_grpc_channel + + +@pytest.mark.parametrize( + "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] +) +@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) +def test_budget_service_grpc_transport_channel_mtls_with_adc( + grpc_create_channel, api_mtls_endpoint +): + # Check that if channel and client_cert_source are None, but api_mtls_endpoint + # is provided, then a mTLS channel will be created with SSL ADC. + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + # Mock google.auth.transport.grpc.SslCredentials class. + mock_ssl_cred = mock.Mock() + with mock.patch.multiple( + "google.auth.transport.grpc.SslCredentials", + __init__=mock.Mock(return_value=None), + ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), + ): + mock_cred = mock.Mock() + transport = transports.BudgetServiceGrpcTransport( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint=api_mtls_endpoint, + client_cert_source=None, + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + ) + assert transport.grpc_channel == mock_grpc_channel + + +@pytest.mark.parametrize( + "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] +) +@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) +def test_budget_service_grpc_asyncio_transport_channel_mtls_with_adc( + grpc_create_channel, api_mtls_endpoint +): + # Check that if channel and client_cert_source are None, but api_mtls_endpoint + # is provided, then a mTLS channel will be created with SSL ADC. + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + # Mock google.auth.transport.grpc.SslCredentials class. + mock_ssl_cred = mock.Mock() + with mock.patch.multiple( + "google.auth.transport.grpc.SslCredentials", + __init__=mock.Mock(return_value=None), + ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), + ): + mock_cred = mock.Mock() + transport = transports.BudgetServiceGrpcAsyncIOTransport( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint=api_mtls_endpoint, + client_cert_source=None, + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + ) + assert transport.grpc_channel == mock_grpc_channel + + +def test_budget_path(): + billing_account = "squid" + budget = "clam" + + expected = "billingAccounts/{billing_account}/budgets/{budget}".format( + billing_account=billing_account, budget=budget, + ) + actual = BudgetServiceClient.budget_path(billing_account, budget) + assert expected == actual + + +def test_parse_budget_path(): + expected = { + "billing_account": "whelk", + "budget": "octopus", + } + path = BudgetServiceClient.budget_path(**expected) + + # Check that the path construction is reversible. + actual = BudgetServiceClient.parse_budget_path(path) + assert expected == actual diff --git a/tests/unit/gapic/v1beta1/test_budget_service_client_v1beta1.py b/tests/unit/gapic/v1beta1/test_budget_service_client_v1beta1.py deleted file mode 100644 index 8fa8bc5..0000000 --- a/tests/unit/gapic/v1beta1/test_budget_service_client_v1beta1.py +++ /dev/null @@ -1,261 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# 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. - -"""Unit tests.""" - -import mock -import pytest - -from google.cloud import billing_budgets_v1beta1 -from google.cloud.billing_budgets_v1beta1.proto import budget_model_pb2 -from google.cloud.billing_budgets_v1beta1.proto import budget_service_pb2 -from google.protobuf import empty_pb2 - - -class MultiCallableStub(object): - """Stub for the grpc.UnaryUnaryMultiCallable interface.""" - - def __init__(self, method, channel_stub): - self.method = method - self.channel_stub = channel_stub - - def __call__(self, request, timeout=None, metadata=None, credentials=None): - self.channel_stub.requests.append((self.method, request)) - - response = None - if self.channel_stub.responses: - response = self.channel_stub.responses.pop() - - if isinstance(response, Exception): - raise response - - if response: - return response - - -class ChannelStub(object): - """Stub for the grpc.Channel interface.""" - - def __init__(self, responses=[]): - self.responses = responses - self.requests = [] - - def unary_unary(self, method, request_serializer=None, response_deserializer=None): - return MultiCallableStub(method, self) - - -class CustomException(Exception): - pass - - -class TestBudgetServiceClient(object): - def test_create_budget(self): - # Setup Expected Response - name = "name3373707" - display_name = "displayName1615086568" - etag = "etag3123477" - expected_response = {"name": name, "display_name": display_name, "etag": etag} - expected_response = budget_model_pb2.Budget(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup Request - parent = client.billing_account_path("[BILLING_ACCOUNT]") - budget = {} - - response = client.create_budget(parent, budget) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = budget_service_pb2.CreateBudgetRequest( - parent=parent, budget=budget - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_create_budget_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup request - parent = client.billing_account_path("[BILLING_ACCOUNT]") - budget = {} - - with pytest.raises(CustomException): - client.create_budget(parent, budget) - - def test_update_budget(self): - # Setup Expected Response - name = "name3373707" - display_name = "displayName1615086568" - etag = "etag3123477" - expected_response = {"name": name, "display_name": display_name, "etag": etag} - expected_response = budget_model_pb2.Budget(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup Request - budget = {} - - response = client.update_budget(budget) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = budget_service_pb2.UpdateBudgetRequest(budget=budget) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_update_budget_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup request - budget = {} - - with pytest.raises(CustomException): - client.update_budget(budget) - - def test_get_budget(self): - # Setup Expected Response - name_2 = "name2-1052831874" - display_name = "displayName1615086568" - etag = "etag3123477" - expected_response = {"name": name_2, "display_name": display_name, "etag": etag} - expected_response = budget_model_pb2.Budget(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup Request - name = client.budget_path("[BILLING_ACCOUNT]", "[BUDGET]") - - response = client.get_budget(name) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = budget_service_pb2.GetBudgetRequest(name=name) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_get_budget_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup request - name = client.budget_path("[BILLING_ACCOUNT]", "[BUDGET]") - - with pytest.raises(CustomException): - client.get_budget(name) - - def test_list_budgets(self): - # Setup Expected Response - next_page_token = "" - budgets_element = {} - budgets = [budgets_element] - expected_response = {"next_page_token": next_page_token, "budgets": budgets} - expected_response = budget_service_pb2.ListBudgetsResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup Request - parent = client.billing_account_path("[BILLING_ACCOUNT]") - - paged_list_response = client.list_budgets(parent) - resources = list(paged_list_response) - assert len(resources) == 1 - - assert expected_response.budgets[0] == resources[0] - - assert len(channel.requests) == 1 - expected_request = budget_service_pb2.ListBudgetsRequest(parent=parent) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_list_budgets_exception(self): - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup request - parent = client.billing_account_path("[BILLING_ACCOUNT]") - - paged_list_response = client.list_budgets(parent) - with pytest.raises(CustomException): - list(paged_list_response) - - def test_delete_budget(self): - channel = ChannelStub() - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup Request - name = client.budget_path("[BILLING_ACCOUNT]", "[BUDGET]") - - client.delete_budget(name) - - assert len(channel.requests) == 1 - expected_request = budget_service_pb2.DeleteBudgetRequest(name=name) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_delete_budget_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup request - name = client.budget_path("[BILLING_ACCOUNT]", "[BUDGET]") - - with pytest.raises(CustomException): - client.delete_budget(name)