diff --git a/google/cloud/bigquery_reservation/__init__.py b/google/cloud/bigquery_reservation/__init__.py index 60f322a8..c3cb7417 100644 --- a/google/cloud/bigquery_reservation/__init__.py +++ b/google/cloud/bigquery_reservation/__init__.py @@ -72,6 +72,12 @@ ) from google.cloud.bigquery_reservation_v1.types.reservation import MoveAssignmentRequest from google.cloud.bigquery_reservation_v1.types.reservation import Reservation +from google.cloud.bigquery_reservation_v1.types.reservation import ( + SearchAllAssignmentsRequest, +) +from google.cloud.bigquery_reservation_v1.types.reservation import ( + SearchAllAssignmentsResponse, +) from google.cloud.bigquery_reservation_v1.types.reservation import ( SearchAssignmentsRequest, ) @@ -118,6 +124,8 @@ "MergeCapacityCommitmentsRequest", "MoveAssignmentRequest", "Reservation", + "SearchAllAssignmentsRequest", + "SearchAllAssignmentsResponse", "SearchAssignmentsRequest", "SearchAssignmentsResponse", "SplitCapacityCommitmentRequest", diff --git a/google/cloud/bigquery_reservation_v1/__init__.py b/google/cloud/bigquery_reservation_v1/__init__.py index 5902a13e..f4565cda 100644 --- a/google/cloud/bigquery_reservation_v1/__init__.py +++ b/google/cloud/bigquery_reservation_v1/__init__.py @@ -38,6 +38,8 @@ from .types.reservation import MergeCapacityCommitmentsRequest from .types.reservation import MoveAssignmentRequest from .types.reservation import Reservation +from .types.reservation import SearchAllAssignmentsRequest +from .types.reservation import SearchAllAssignmentsResponse from .types.reservation import SearchAssignmentsRequest from .types.reservation import SearchAssignmentsResponse from .types.reservation import SplitCapacityCommitmentRequest @@ -70,6 +72,8 @@ "MoveAssignmentRequest", "Reservation", "ReservationServiceClient", + "SearchAllAssignmentsRequest", + "SearchAllAssignmentsResponse", "SearchAssignmentsRequest", "SearchAssignmentsResponse", "SplitCapacityCommitmentRequest", diff --git a/google/cloud/bigquery_reservation_v1/gapic_metadata.json b/google/cloud/bigquery_reservation_v1/gapic_metadata.json index 801191bf..d8fad3d5 100644 --- a/google/cloud/bigquery_reservation_v1/gapic_metadata.json +++ b/google/cloud/bigquery_reservation_v1/gapic_metadata.json @@ -80,6 +80,11 @@ "move_assignment" ] }, + "SearchAllAssignments": { + "methods": [ + "search_all_assignments" + ] + }, "SearchAssignments": { "methods": [ "search_assignments" @@ -180,6 +185,11 @@ "move_assignment" ] }, + "SearchAllAssignments": { + "methods": [ + "search_all_assignments" + ] + }, "SearchAssignments": { "methods": [ "search_assignments" diff --git a/google/cloud/bigquery_reservation_v1/services/reservation_service/async_client.py b/google/cloud/bigquery_reservation_v1/services/reservation_service/async_client.py index 148a7601..fc2c5f10 100644 --- a/google/cloud/bigquery_reservation_v1/services/reservation_service/async_client.py +++ b/google/cloud/bigquery_reservation_v1/services/reservation_service/async_client.py @@ -18,6 +18,7 @@ import re from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources +import warnings import google.api_core.client_options as ClientOptions # type: ignore from google.api_core import exceptions as core_exceptions # type: ignore @@ -274,7 +275,7 @@ async def create_reservation( # and friendly error handling. rpc = gapic_v1.method_async.wrap_method( self._client._transport.create_reservation, - default_timeout=60.0, + default_timeout=300.0, client_info=DEFAULT_CLIENT_INFO, ) @@ -603,7 +604,7 @@ async def update_reservation( # and friendly error handling. rpc = gapic_v1.method_async.wrap_method( self._client._transport.update_reservation, - default_timeout=60.0, + default_timeout=300.0, client_info=DEFAULT_CLIENT_INFO, ) @@ -698,7 +699,7 @@ async def create_capacity_commitment( # and friendly error handling. rpc = gapic_v1.method_async.wrap_method( self._client._transport.create_capacity_commitment, - default_timeout=60.0, + default_timeout=300.0, client_info=DEFAULT_CLIENT_INFO, ) @@ -1060,7 +1061,7 @@ async def update_capacity_commitment( # and friendly error handling. rpc = gapic_v1.method_async.wrap_method( self._client._transport.update_capacity_commitment, - default_timeout=60.0, + default_timeout=300.0, client_info=DEFAULT_CLIENT_INFO, ) @@ -1151,7 +1152,7 @@ async def split_capacity_commitment( # and friendly error handling. rpc = gapic_v1.method_async.wrap_method( self._client._transport.split_capacity_commitment, - default_timeout=60.0, + default_timeout=300.0, client_info=DEFAULT_CLIENT_INFO, ) @@ -1258,7 +1259,7 @@ async def merge_capacity_commitments( # and friendly error handling. rpc = gapic_v1.method_async.wrap_method( self._client._transport.merge_capacity_commitments, - default_timeout=60.0, + default_timeout=300.0, client_info=DEFAULT_CLIENT_INFO, ) @@ -1310,6 +1311,12 @@ async def create_assignment( ``project1``, and ``project2``) could all be created and mapped to the same or different reservations. + "None" assignments represent an absence of the assignment. + Projects assigned to None use on-demand pricing. To create a + "None" assignment, use "none" as a reservation_id in the parent. + Example parent: + ``projects/myproject/locations/US/reservations/none``. + Returns ``google.rpc.Code.PERMISSION_DENIED`` if user does not have 'bigquery.admin' permissions on the project using the reservation and the project that owns this reservation. @@ -1372,7 +1379,7 @@ async def create_assignment( # and friendly error handling. rpc = gapic_v1.method_async.wrap_method( self._client._transport.create_assignment, - default_timeout=60.0, + default_timeout=300.0, client_info=DEFAULT_CLIENT_INFO, ) @@ -1605,8 +1612,8 @@ async def search_assignments( timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.SearchAssignmentsAsyncPager: - r"""Looks up assignments for a specified resource for a particular - region. If the request is about a project: + r"""Deprecated: Looks up assignments for a specified resource for a + particular region. If the request is about a project: 1. Assignments created on the project will be returned if they exist. @@ -1673,6 +1680,11 @@ async def search_assignments( resolve additional pages automatically. """ + warnings.warn( + "ReservationServiceAsyncClient.search_assignments is deprecated", + DeprecationWarning, + ) + # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. @@ -1728,6 +1740,127 @@ async def search_assignments( # Done; return the response. return response + async def search_all_assignments( + self, + request: reservation.SearchAllAssignmentsRequest = None, + *, + parent: str = None, + query: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> pagers.SearchAllAssignmentsAsyncPager: + r"""Looks up assignments for a specified resource for a particular + region. If the request is about a project: + + 1. Assignments created on the project will be returned if they + exist. + 2. Otherwise assignments created on the closest ancestor will be + returned. + 3. Assignments for different JobTypes will all be returned. + + The same logic applies if the request is about a folder. + + If the request is about an organization, then assignments + created on the organization will be returned (organization + doesn't have ancestors). + + Comparing to ListAssignments, there are some behavior + differences: + + 1. permission on the assignee will be verified in this API. + 2. Hierarchy lookup (project->folder->organization) happens in + this API. + 3. Parent here is ``projects/*/locations/*``, instead of + ``projects/*/locations/*reservations/*``. + + Args: + request (:class:`google.cloud.bigquery_reservation_v1.types.SearchAllAssignmentsRequest`): + The request object. The request for + [ReservationService.SearchAllAssignments][google.cloud.bigquery.reservation.v1.ReservationService.SearchAllAssignments]. + Note: "bigquery.reservationAssignments.search" + permission is required on the related assignee. + parent (:class:`str`): + Required. The resource name with location (project name + could be the wildcard '-'), e.g.: + ``projects/-/locations/US``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + query (:class:`str`): + Please specify resource name as assignee in the query. + + Examples: + + - ``assignee=projects/myproject`` + - ``assignee=folders/123`` + - ``assignee=organizations/456`` + + + This corresponds to the ``query`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.bigquery_reservation_v1.services.reservation_service.pagers.SearchAllAssignmentsAsyncPager: + The response for + [ReservationService.SearchAllAssignments][google.cloud.bigquery.reservation.v1.ReservationService.SearchAllAssignments]. + + Iterating over this object will yield results and + resolve additional pages automatically. + + """ + # Create or coerce a protobuf request object. + # Sanity check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent, query]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + request = reservation.SearchAllAssignmentsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if query is not None: + request.query = query + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.search_all_assignments, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # This method is paged; wrap the response in a pager, which provides + # an `__aiter__` convenience method. + response = pagers.SearchAllAssignmentsAsyncPager( + method=rpc, request=request, response=response, metadata=metadata, + ) + + # Done; return the response. + return response + async def move_assignment( self, request: reservation.MoveAssignmentRequest = None, @@ -1804,7 +1937,7 @@ async def move_assignment( # and friendly error handling. rpc = gapic_v1.method_async.wrap_method( self._client._transport.move_assignment, - default_timeout=60.0, + default_timeout=300.0, client_info=DEFAULT_CLIENT_INFO, ) @@ -1838,7 +1971,7 @@ async def get_bi_reservation( name (:class:`str`): Required. Name of the requested reservation, for example: - ``projects/{project_id}/locations/{location_id}/bireservation`` + ``projects/{project_id}/locations/{location_id}/biReservation`` This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this @@ -1968,7 +2101,7 @@ async def update_bi_reservation( # and friendly error handling. rpc = gapic_v1.method_async.wrap_method( self._client._transport.update_bi_reservation, - default_timeout=60.0, + default_timeout=300.0, client_info=DEFAULT_CLIENT_INFO, ) diff --git a/google/cloud/bigquery_reservation_v1/services/reservation_service/client.py b/google/cloud/bigquery_reservation_v1/services/reservation_service/client.py index b7d10d38..0a659a66 100644 --- a/google/cloud/bigquery_reservation_v1/services/reservation_service/client.py +++ b/google/cloud/bigquery_reservation_v1/services/reservation_service/client.py @@ -19,6 +19,7 @@ import re from typing import Callable, Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources +import warnings from google.api_core import client_options as client_options_lib # type: ignore from google.api_core import exceptions as core_exceptions # type: ignore @@ -202,7 +203,7 @@ def parse_assignment_path(path: str) -> Dict[str, str]: @staticmethod def bi_reservation_path(project: str, location: str,) -> str: """Returns a fully-qualified bi_reservation string.""" - return "projects/{project}/locations/{location}/bireservation".format( + return "projects/{project}/locations/{location}/biReservation".format( project=project, location=location, ) @@ -210,7 +211,7 @@ def bi_reservation_path(project: str, location: str,) -> str: def parse_bi_reservation_path(path: str) -> Dict[str, str]: """Parses a bi_reservation path into its component segments.""" m = re.match( - r"^projects/(?P.+?)/locations/(?P.+?)/bireservation$", + r"^projects/(?P.+?)/locations/(?P.+?)/biReservation$", path, ) return m.groupdict() if m else {} @@ -1493,6 +1494,12 @@ def create_assignment( ``project1``, and ``project2``) could all be created and mapped to the same or different reservations. + "None" assignments represent an absence of the assignment. + Projects assigned to None use on-demand pricing. To create a + "None" assignment, use "none" as a reservation_id in the parent. + Example parent: + ``projects/myproject/locations/US/reservations/none``. + Returns ``google.rpc.Code.PERMISSION_DENIED`` if user does not have 'bigquery.admin' permissions on the project using the reservation and the project that owns this reservation. @@ -1768,8 +1775,8 @@ def search_assignments( timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.SearchAssignmentsPager: - r"""Looks up assignments for a specified resource for a particular - region. If the request is about a project: + r"""Deprecated: Looks up assignments for a specified resource for a + particular region. If the request is about a project: 1. Assignments created on the project will be returned if they exist. @@ -1836,6 +1843,11 @@ def search_assignments( resolve additional pages automatically. """ + warnings.warn( + "ReservationServiceClient.search_assignments is deprecated", + DeprecationWarning, + ) + # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. @@ -1881,6 +1893,127 @@ def search_assignments( # Done; return the response. return response + def search_all_assignments( + self, + request: reservation.SearchAllAssignmentsRequest = None, + *, + parent: str = None, + query: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> pagers.SearchAllAssignmentsPager: + r"""Looks up assignments for a specified resource for a particular + region. If the request is about a project: + + 1. Assignments created on the project will be returned if they + exist. + 2. Otherwise assignments created on the closest ancestor will be + returned. + 3. Assignments for different JobTypes will all be returned. + + The same logic applies if the request is about a folder. + + If the request is about an organization, then assignments + created on the organization will be returned (organization + doesn't have ancestors). + + Comparing to ListAssignments, there are some behavior + differences: + + 1. permission on the assignee will be verified in this API. + 2. Hierarchy lookup (project->folder->organization) happens in + this API. + 3. Parent here is ``projects/*/locations/*``, instead of + ``projects/*/locations/*reservations/*``. + + Args: + request (google.cloud.bigquery_reservation_v1.types.SearchAllAssignmentsRequest): + The request object. The request for + [ReservationService.SearchAllAssignments][google.cloud.bigquery.reservation.v1.ReservationService.SearchAllAssignments]. + Note: "bigquery.reservationAssignments.search" + permission is required on the related assignee. + parent (str): + Required. The resource name with location (project name + could be the wildcard '-'), e.g.: + ``projects/-/locations/US``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + query (str): + Please specify resource name as assignee in the query. + + Examples: + + - ``assignee=projects/myproject`` + - ``assignee=folders/123`` + - ``assignee=organizations/456`` + + + This corresponds to the ``query`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.bigquery_reservation_v1.services.reservation_service.pagers.SearchAllAssignmentsPager: + The response for + [ReservationService.SearchAllAssignments][google.cloud.bigquery.reservation.v1.ReservationService.SearchAllAssignments]. + + Iterating over this object will yield results and + resolve additional pages automatically. + + """ + # Create or coerce a protobuf request object. + # Sanity check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent, query]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a reservation.SearchAllAssignmentsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, reservation.SearchAllAssignmentsRequest): + request = reservation.SearchAllAssignmentsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if query is not None: + request.query = query + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.search_all_assignments] + + # 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.SearchAllAssignmentsPager( + method=rpc, request=request, response=response, metadata=metadata, + ) + + # Done; return the response. + return response + def move_assignment( self, request: reservation.MoveAssignmentRequest = None, @@ -1991,7 +2124,7 @@ def get_bi_reservation( name (str): Required. Name of the requested reservation, for example: - ``projects/{project_id}/locations/{location_id}/bireservation`` + ``projects/{project_id}/locations/{location_id}/biReservation`` This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this diff --git a/google/cloud/bigquery_reservation_v1/services/reservation_service/pagers.py b/google/cloud/bigquery_reservation_v1/services/reservation_service/pagers.py index cda6ca16..2642b0d1 100644 --- a/google/cloud/bigquery_reservation_v1/services/reservation_service/pagers.py +++ b/google/cloud/bigquery_reservation_v1/services/reservation_service/pagers.py @@ -537,3 +537,131 @@ async def async_generator(): def __repr__(self) -> str: return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class SearchAllAssignmentsPager: + """A pager for iterating through ``search_all_assignments`` requests. + + This class thinly wraps an initial + :class:`google.cloud.bigquery_reservation_v1.types.SearchAllAssignmentsResponse` object, and + provides an ``__iter__`` method to iterate through its + ``assignments`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``SearchAllAssignments`` requests and continue to iterate + through the ``assignments`` field on the + corresponding responses. + + All the usual :class:`google.cloud.bigquery_reservation_v1.types.SearchAllAssignmentsResponse` + 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[..., reservation.SearchAllAssignmentsResponse], + request: reservation.SearchAllAssignmentsRequest, + response: reservation.SearchAllAssignmentsResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.bigquery_reservation_v1.types.SearchAllAssignmentsRequest): + The initial request object. + response (google.cloud.bigquery_reservation_v1.types.SearchAllAssignmentsResponse): + 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 = reservation.SearchAllAssignmentsRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages(self) -> Iterable[reservation.SearchAllAssignmentsResponse]: + 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[reservation.Assignment]: + for page in self.pages: + yield from page.assignments + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class SearchAllAssignmentsAsyncPager: + """A pager for iterating through ``search_all_assignments`` requests. + + This class thinly wraps an initial + :class:`google.cloud.bigquery_reservation_v1.types.SearchAllAssignmentsResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``assignments`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``SearchAllAssignments`` requests and continue to iterate + through the ``assignments`` field on the + corresponding responses. + + All the usual :class:`google.cloud.bigquery_reservation_v1.types.SearchAllAssignmentsResponse` + 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[reservation.SearchAllAssignmentsResponse]], + request: reservation.SearchAllAssignmentsRequest, + response: reservation.SearchAllAssignmentsResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiates the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.bigquery_reservation_v1.types.SearchAllAssignmentsRequest): + The initial request object. + response (google.cloud.bigquery_reservation_v1.types.SearchAllAssignmentsResponse): + 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 = reservation.SearchAllAssignmentsRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + async def pages(self) -> AsyncIterable[reservation.SearchAllAssignmentsResponse]: + 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[reservation.Assignment]: + async def async_generator(): + async for page in self.pages: + for response in page.assignments: + yield response + + return async_generator() + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) diff --git a/google/cloud/bigquery_reservation_v1/services/reservation_service/transports/base.py b/google/cloud/bigquery_reservation_v1/services/reservation_service/transports/base.py index cfede142..a15584b1 100644 --- a/google/cloud/bigquery_reservation_v1/services/reservation_service/transports/base.py +++ b/google/cloud/bigquery_reservation_v1/services/reservation_service/transports/base.py @@ -160,7 +160,7 @@ def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { self.create_reservation: gapic_v1.method.wrap_method( - self.create_reservation, default_timeout=60.0, client_info=client_info, + self.create_reservation, default_timeout=300.0, client_info=client_info, ), self.list_reservations: gapic_v1.method.wrap_method( self.list_reservations, @@ -208,11 +208,11 @@ def _prep_wrapped_messages(self, client_info): client_info=client_info, ), self.update_reservation: gapic_v1.method.wrap_method( - self.update_reservation, default_timeout=60.0, client_info=client_info, + self.update_reservation, default_timeout=300.0, client_info=client_info, ), self.create_capacity_commitment: gapic_v1.method.wrap_method( self.create_capacity_commitment, - default_timeout=60.0, + default_timeout=300.0, client_info=client_info, ), self.list_capacity_commitments: gapic_v1.method.wrap_method( @@ -262,21 +262,21 @@ def _prep_wrapped_messages(self, client_info): ), self.update_capacity_commitment: gapic_v1.method.wrap_method( self.update_capacity_commitment, - default_timeout=60.0, + default_timeout=300.0, client_info=client_info, ), self.split_capacity_commitment: gapic_v1.method.wrap_method( self.split_capacity_commitment, - default_timeout=60.0, + default_timeout=300.0, client_info=client_info, ), self.merge_capacity_commitments: gapic_v1.method.wrap_method( self.merge_capacity_commitments, - default_timeout=60.0, + default_timeout=300.0, client_info=client_info, ), self.create_assignment: gapic_v1.method.wrap_method( - self.create_assignment, default_timeout=60.0, client_info=client_info, + self.create_assignment, default_timeout=300.0, client_info=client_info, ), self.list_assignments: gapic_v1.method.wrap_method( self.list_assignments, @@ -323,8 +323,13 @@ def _prep_wrapped_messages(self, client_info): default_timeout=60.0, client_info=client_info, ), + self.search_all_assignments: gapic_v1.method.wrap_method( + self.search_all_assignments, + default_timeout=None, + client_info=client_info, + ), self.move_assignment: gapic_v1.method.wrap_method( - self.move_assignment, default_timeout=60.0, client_info=client_info, + self.move_assignment, default_timeout=300.0, client_info=client_info, ), self.get_bi_reservation: gapic_v1.method.wrap_method( self.get_bi_reservation, @@ -343,7 +348,7 @@ def _prep_wrapped_messages(self, client_info): ), self.update_bi_reservation: gapic_v1.method.wrap_method( self.update_bi_reservation, - default_timeout=60.0, + default_timeout=300.0, client_info=client_info, ), } @@ -515,6 +520,18 @@ def search_assignments( ]: raise NotImplementedError() + @property + def search_all_assignments( + self, + ) -> Callable[ + [reservation.SearchAllAssignmentsRequest], + Union[ + reservation.SearchAllAssignmentsResponse, + Awaitable[reservation.SearchAllAssignmentsResponse], + ], + ]: + raise NotImplementedError() + @property def move_assignment( self, diff --git a/google/cloud/bigquery_reservation_v1/services/reservation_service/transports/grpc.py b/google/cloud/bigquery_reservation_v1/services/reservation_service/transports/grpc.py index 3e0ac2fb..9e465a64 100644 --- a/google/cloud/bigquery_reservation_v1/services/reservation_service/transports/grpc.py +++ b/google/cloud/bigquery_reservation_v1/services/reservation_service/transports/grpc.py @@ -637,6 +637,12 @@ def create_assignment( ``project1``, and ``project2``) could all be created and mapped to the same or different reservations. + "None" assignments represent an absence of the assignment. + Projects assigned to None use on-demand pricing. To create a + "None" assignment, use "none" as a reservation_id in the parent. + Example parent: + ``projects/myproject/locations/US/reservations/none``. + Returns ``google.rpc.Code.PERMISSION_DENIED`` if user does not have 'bigquery.admin' permissions on the project using the reservation and the project that owns this reservation. @@ -760,8 +766,8 @@ def search_assignments( ]: r"""Return a callable for the search assignments method over gRPC. - Looks up assignments for a specified resource for a particular - region. If the request is about a project: + Deprecated: Looks up assignments for a specified resource for a + particular region. If the request is about a project: 1. Assignments created on the project will be returned if they exist. @@ -804,6 +810,57 @@ def search_assignments( ) return self._stubs["search_assignments"] + @property + def search_all_assignments( + self, + ) -> Callable[ + [reservation.SearchAllAssignmentsRequest], + reservation.SearchAllAssignmentsResponse, + ]: + r"""Return a callable for the search all assignments method over gRPC. + + Looks up assignments for a specified resource for a particular + region. If the request is about a project: + + 1. Assignments created on the project will be returned if they + exist. + 2. Otherwise assignments created on the closest ancestor will be + returned. + 3. Assignments for different JobTypes will all be returned. + + The same logic applies if the request is about a folder. + + If the request is about an organization, then assignments + created on the organization will be returned (organization + doesn't have ancestors). + + Comparing to ListAssignments, there are some behavior + differences: + + 1. permission on the assignee will be verified in this API. + 2. Hierarchy lookup (project->folder->organization) happens in + this API. + 3. Parent here is ``projects/*/locations/*``, instead of + ``projects/*/locations/*reservations/*``. + + Returns: + Callable[[~.SearchAllAssignmentsRequest], + ~.SearchAllAssignmentsResponse]: + 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 "search_all_assignments" not in self._stubs: + self._stubs["search_all_assignments"] = self.grpc_channel.unary_unary( + "/google.cloud.bigquery.reservation.v1.ReservationService/SearchAllAssignments", + request_serializer=reservation.SearchAllAssignmentsRequest.serialize, + response_deserializer=reservation.SearchAllAssignmentsResponse.deserialize, + ) + return self._stubs["search_all_assignments"] + @property def move_assignment( self, diff --git a/google/cloud/bigquery_reservation_v1/services/reservation_service/transports/grpc_asyncio.py b/google/cloud/bigquery_reservation_v1/services/reservation_service/transports/grpc_asyncio.py index 947ea80e..573bbf71 100644 --- a/google/cloud/bigquery_reservation_v1/services/reservation_service/transports/grpc_asyncio.py +++ b/google/cloud/bigquery_reservation_v1/services/reservation_service/transports/grpc_asyncio.py @@ -653,6 +653,12 @@ def create_assignment( ``project1``, and ``project2``) could all be created and mapped to the same or different reservations. + "None" assignments represent an absence of the assignment. + Projects assigned to None use on-demand pricing. To create a + "None" assignment, use "none" as a reservation_id in the parent. + Example parent: + ``projects/myproject/locations/US/reservations/none``. + Returns ``google.rpc.Code.PERMISSION_DENIED`` if user does not have 'bigquery.admin' permissions on the project using the reservation and the project that owns this reservation. @@ -778,8 +784,8 @@ def search_assignments( ]: r"""Return a callable for the search assignments method over gRPC. - Looks up assignments for a specified resource for a particular - region. If the request is about a project: + Deprecated: Looks up assignments for a specified resource for a + particular region. If the request is about a project: 1. Assignments created on the project will be returned if they exist. @@ -822,6 +828,57 @@ def search_assignments( ) return self._stubs["search_assignments"] + @property + def search_all_assignments( + self, + ) -> Callable[ + [reservation.SearchAllAssignmentsRequest], + Awaitable[reservation.SearchAllAssignmentsResponse], + ]: + r"""Return a callable for the search all assignments method over gRPC. + + Looks up assignments for a specified resource for a particular + region. If the request is about a project: + + 1. Assignments created on the project will be returned if they + exist. + 2. Otherwise assignments created on the closest ancestor will be + returned. + 3. Assignments for different JobTypes will all be returned. + + The same logic applies if the request is about a folder. + + If the request is about an organization, then assignments + created on the organization will be returned (organization + doesn't have ancestors). + + Comparing to ListAssignments, there are some behavior + differences: + + 1. permission on the assignee will be verified in this API. + 2. Hierarchy lookup (project->folder->organization) happens in + this API. + 3. Parent here is ``projects/*/locations/*``, instead of + ``projects/*/locations/*reservations/*``. + + Returns: + Callable[[~.SearchAllAssignmentsRequest], + Awaitable[~.SearchAllAssignmentsResponse]]: + 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 "search_all_assignments" not in self._stubs: + self._stubs["search_all_assignments"] = self.grpc_channel.unary_unary( + "/google.cloud.bigquery.reservation.v1.ReservationService/SearchAllAssignments", + request_serializer=reservation.SearchAllAssignmentsRequest.serialize, + response_deserializer=reservation.SearchAllAssignmentsResponse.deserialize, + ) + return self._stubs["search_all_assignments"] + @property def move_assignment( self, diff --git a/google/cloud/bigquery_reservation_v1/types/__init__.py b/google/cloud/bigquery_reservation_v1/types/__init__.py index 2e2d2b78..abaf41b3 100644 --- a/google/cloud/bigquery_reservation_v1/types/__init__.py +++ b/google/cloud/bigquery_reservation_v1/types/__init__.py @@ -35,6 +35,8 @@ MergeCapacityCommitmentsRequest, MoveAssignmentRequest, Reservation, + SearchAllAssignmentsRequest, + SearchAllAssignmentsResponse, SearchAssignmentsRequest, SearchAssignmentsResponse, SplitCapacityCommitmentRequest, @@ -66,6 +68,8 @@ "MergeCapacityCommitmentsRequest", "MoveAssignmentRequest", "Reservation", + "SearchAllAssignmentsRequest", + "SearchAllAssignmentsResponse", "SearchAssignmentsRequest", "SearchAssignmentsResponse", "SplitCapacityCommitmentRequest", diff --git a/google/cloud/bigquery_reservation_v1/types/reservation.py b/google/cloud/bigquery_reservation_v1/types/reservation.py index ab6c8e69..e409852a 100644 --- a/google/cloud/bigquery_reservation_v1/types/reservation.py +++ b/google/cloud/bigquery_reservation_v1/types/reservation.py @@ -46,7 +46,9 @@ "ListAssignmentsResponse", "DeleteAssignmentRequest", "SearchAssignmentsRequest", + "SearchAllAssignmentsRequest", "SearchAssignmentsResponse", + "SearchAllAssignmentsResponse", "MoveAssignmentRequest", "BiReservation", "GetBiReservationRequest", @@ -77,16 +79,26 @@ class Reservation(proto.Message): capacity, the request will fail with ``google.rpc.Code.RESOURCE_EXHAUSTED``. ignore_idle_slots (bool): - If false, any query using this reservation - will use idle slots from other reservations - within the same admin project. If true, a query - using this reservation will execute with the - slot capacity specified above at most. + If false, any query or pipeline job using this reservation + will use idle slots from other reservations within the same + admin project. If true, a query or pipeline job using this + reservation will execute with the slot capacity specified in + the slot_capacity field at most. + creation_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. Creation time of the + reservation. + update_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. Last update time of the + reservation. """ name = proto.Field(proto.STRING, number=1,) slot_capacity = proto.Field(proto.INT64, number=2,) ignore_idle_slots = proto.Field(proto.BOOL, number=4,) + creation_time = proto.Field( + proto.MESSAGE, number=8, message=timestamp_pb2.Timestamp, + ) + update_time = proto.Field(proto.MESSAGE, number=9, message=timestamp_pb2.Timestamp,) class CapacityCommitment(proto.Message): @@ -112,6 +124,10 @@ class CapacityCommitment(proto.Message): Capacity commitment commitment plan. state (google.cloud.bigquery_reservation_v1.types.CapacityCommitment.State): Output only. State of the commitment. + commitment_start_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The start of the current + commitment period. It is applicable only for + ACTIVE capacity commitments. commitment_end_time (google.protobuf.timestamp_pb2.Timestamp): Output only. The end of the current commitment period. It is applicable only for @@ -150,6 +166,9 @@ class State(proto.Enum): slot_count = proto.Field(proto.INT64, number=2,) plan = proto.Field(proto.ENUM, number=3, enum=CommitmentPlan,) state = proto.Field(proto.ENUM, number=4, enum=State,) + commitment_start_time = proto.Field( + proto.MESSAGE, number=9, message=timestamp_pb2.Timestamp, + ) commitment_end_time = proto.Field( proto.MESSAGE, number=5, message=timestamp_pb2.Timestamp, ) @@ -279,6 +298,14 @@ class CreateCapacityCommitmentRequest(proto.Message): enforce_single_admin_project_per_org (bool): If true, fail the request if another project in the organization has a capacity commitment. + capacity_commitment_id (str): + The optional capacity commitment ID. Capacity + commitment name will be generated automatically + if this field is empty. This field must only + contain lower case alphanumeric characters or + dash. Max length is 64 characters. + NOTE: this ID won't be kept if the capacity + commitment is split or merged. """ parent = proto.Field(proto.STRING, number=1,) @@ -286,6 +313,7 @@ class CreateCapacityCommitmentRequest(proto.Message): proto.MESSAGE, number=2, message="CapacityCommitment", ) enforce_single_admin_project_per_org = proto.Field(proto.BOOL, number=4,) + capacity_commitment_id = proto.Field(proto.STRING, number=5,) class ListCapacityCommitmentsRequest(proto.Message): @@ -355,9 +383,15 @@ class DeleteCapacityCommitmentRequest(proto.Message): Required. Resource name of the capacity commitment to delete. E.g., ``projects/myproject/locations/US/capacityCommitments/123`` + force (bool): + Can be used to force delete commitments even + if assignments exist. Deleting commitments with + assignments may cause queries to fail if they no + longer have access to slots. """ name = proto.Field(proto.STRING, number=1,) + force = proto.Field(proto.BOOL, number=3,) class UpdateCapacityCommitmentRequest(proto.Message): @@ -460,6 +494,7 @@ class JobType(proto.Enum): JOB_TYPE_UNSPECIFIED = 0 PIPELINE = 1 QUERY = 2 + ML_EXTERNAL = 3 class State(proto.Enum): r"""Assignment will remain in PENDING state if no active capacity @@ -488,10 +523,17 @@ class CreateAssignmentRequest(proto.Message): ``projects/myproject/locations/US/reservations/team1-prod`` assignment (google.cloud.bigquery_reservation_v1.types.Assignment): Assignment resource to create. + assignment_id (str): + The optional assignment ID. Assignment name + will be generated automatically if this field is + empty. This field must only contain lower case + alphanumeric characters or dash. Max length is + 64 characters. """ parent = proto.Field(proto.STRING, number=1,) assignment = proto.Field(proto.MESSAGE, number=2, message="Assignment",) + assignment_id = proto.Field(proto.STRING, number=4,) class ListAssignmentsRequest(proto.Message): @@ -589,6 +631,39 @@ class SearchAssignmentsRequest(proto.Message): page_token = proto.Field(proto.STRING, number=4,) +class SearchAllAssignmentsRequest(proto.Message): + r"""The request for + [ReservationService.SearchAllAssignments][google.cloud.bigquery.reservation.v1.ReservationService.SearchAllAssignments]. + Note: "bigquery.reservationAssignments.search" permission is + required on the related assignee. + + Attributes: + parent (str): + Required. The resource name with location (project name + could be the wildcard '-'), e.g.: + ``projects/-/locations/US``. + query (str): + Please specify resource name as assignee in the query. + + Examples: + + - ``assignee=projects/myproject`` + - ``assignee=folders/123`` + - ``assignee=organizations/456`` + page_size (int): + The maximum number of items to return per + page. + page_token (str): + The next_page_token value returned from a previous List + request, if any. + """ + + parent = proto.Field(proto.STRING, number=1,) + query = proto.Field(proto.STRING, number=2,) + page_size = proto.Field(proto.INT32, number=3,) + page_token = proto.Field(proto.STRING, number=4,) + + class SearchAssignmentsResponse(proto.Message): r"""The response for [ReservationService.SearchAssignments][google.cloud.bigquery.reservation.v1.ReservationService.SearchAssignments]. @@ -610,6 +685,27 @@ def raw_page(self): next_page_token = proto.Field(proto.STRING, number=2,) +class SearchAllAssignmentsResponse(proto.Message): + r"""The response for + [ReservationService.SearchAllAssignments][google.cloud.bigquery.reservation.v1.ReservationService.SearchAllAssignments]. + + Attributes: + assignments (Sequence[google.cloud.bigquery_reservation_v1.types.Assignment]): + List of assignments visible to the user. + next_page_token (str): + Token to retrieve the next page of results, + or empty if there are no more results in the + list. + """ + + @property + def raw_page(self): + return self + + assignments = proto.RepeatedField(proto.MESSAGE, number=1, message="Assignment",) + next_page_token = proto.Field(proto.STRING, number=2,) + + class MoveAssignmentRequest(proto.Message): r"""The request for [ReservationService.MoveAssignment][google.cloud.bigquery.reservation.v1.ReservationService.MoveAssignment]. @@ -640,7 +736,7 @@ class BiReservation(proto.Message): name (str): The resource name of the singleton BI reservation. Reservation names have the form - ``projects/{project_id}/locations/{location_id}/bireservation``. + ``projects/{project_id}/locations/{location_id}/biReservation``. update_time (google.protobuf.timestamp_pb2.Timestamp): Output only. The last update timestamp of a reservation. @@ -658,7 +754,7 @@ class GetBiReservationRequest(proto.Message): Attributes: name (str): Required. Name of the requested reservation, for example: - ``projects/{project_id}/locations/{location_id}/bireservation`` + ``projects/{project_id}/locations/{location_id}/biReservation`` """ name = proto.Field(proto.STRING, number=1,) diff --git a/scripts/fixup_bigquery_reservation_v1_keywords.py b/scripts/fixup_bigquery_reservation_v1_keywords.py index 381112b8..569bb151 100644 --- a/scripts/fixup_bigquery_reservation_v1_keywords.py +++ b/scripts/fixup_bigquery_reservation_v1_keywords.py @@ -39,11 +39,11 @@ def partition( class bigquery_reservationCallTransformer(cst.CSTTransformer): CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { - 'create_assignment': ('parent', 'assignment', ), - 'create_capacity_commitment': ('parent', 'capacity_commitment', 'enforce_single_admin_project_per_org', ), + 'create_assignment': ('parent', 'assignment', 'assignment_id', ), + 'create_capacity_commitment': ('parent', 'capacity_commitment', 'enforce_single_admin_project_per_org', 'capacity_commitment_id', ), 'create_reservation': ('parent', 'reservation_id', 'reservation', ), 'delete_assignment': ('name', ), - 'delete_capacity_commitment': ('name', ), + 'delete_capacity_commitment': ('name', 'force', ), 'delete_reservation': ('name', ), 'get_bi_reservation': ('name', ), 'get_capacity_commitment': ('name', ), @@ -53,6 +53,7 @@ class bigquery_reservationCallTransformer(cst.CSTTransformer): 'list_reservations': ('parent', 'page_size', 'page_token', ), 'merge_capacity_commitments': ('parent', 'capacity_commitment_ids', ), 'move_assignment': ('name', 'destination_id', ), + 'search_all_assignments': ('parent', 'query', 'page_size', 'page_token', ), 'search_assignments': ('parent', 'query', 'page_size', 'page_token', ), 'split_capacity_commitment': ('name', 'slot_count', ), 'update_bi_reservation': ('bi_reservation', 'update_mask', ), diff --git a/tests/unit/gapic/bigquery_reservation_v1/test_reservation_service.py b/tests/unit/gapic/bigquery_reservation_v1/test_reservation_service.py index 8d356f57..413e9eb5 100644 --- a/tests/unit/gapic/bigquery_reservation_v1/test_reservation_service.py +++ b/tests/unit/gapic/bigquery_reservation_v1/test_reservation_service.py @@ -4903,6 +4903,401 @@ async def test_search_assignments_async_pages(): assert page_.raw_page.next_page_token == token +def test_search_all_assignments( + transport: str = "grpc", request_type=reservation.SearchAllAssignmentsRequest +): + client = ReservationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.search_all_assignments), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = reservation.SearchAllAssignmentsResponse( + next_page_token="next_page_token_value", + ) + response = client.search_all_assignments(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == reservation.SearchAllAssignmentsRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.SearchAllAssignmentsPager) + assert response.next_page_token == "next_page_token_value" + + +def test_search_all_assignments_from_dict(): + test_search_all_assignments(request_type=dict) + + +def test_search_all_assignments_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ReservationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.search_all_assignments), "__call__" + ) as call: + client.search_all_assignments() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == reservation.SearchAllAssignmentsRequest() + + +@pytest.mark.asyncio +async def test_search_all_assignments_async( + transport: str = "grpc_asyncio", + request_type=reservation.SearchAllAssignmentsRequest, +): + client = ReservationServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.search_all_assignments), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + reservation.SearchAllAssignmentsResponse( + next_page_token="next_page_token_value", + ) + ) + response = await client.search_all_assignments(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == reservation.SearchAllAssignmentsRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.SearchAllAssignmentsAsyncPager) + assert response.next_page_token == "next_page_token_value" + + +@pytest.mark.asyncio +async def test_search_all_assignments_async_from_dict(): + await test_search_all_assignments_async(request_type=dict) + + +def test_search_all_assignments_field_headers(): + client = ReservationServiceClient( + credentials=ga_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 = reservation.SearchAllAssignmentsRequest() + + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.search_all_assignments), "__call__" + ) as call: + call.return_value = reservation.SearchAllAssignmentsResponse() + client.search_all_assignments(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_search_all_assignments_field_headers_async(): + client = ReservationServiceAsyncClient( + credentials=ga_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 = reservation.SearchAllAssignmentsRequest() + + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.search_all_assignments), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + reservation.SearchAllAssignmentsResponse() + ) + await client.search_all_assignments(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_search_all_assignments_flattened(): + client = ReservationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.search_all_assignments), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = reservation.SearchAllAssignmentsResponse() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.search_all_assignments( + parent="parent_value", query="query_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0].parent == "parent_value" + assert args[0].query == "query_value" + + +def test_search_all_assignments_flattened_error(): + client = ReservationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.search_all_assignments( + reservation.SearchAllAssignmentsRequest(), + parent="parent_value", + query="query_value", + ) + + +@pytest.mark.asyncio +async def test_search_all_assignments_flattened_async(): + client = ReservationServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.search_all_assignments), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = reservation.SearchAllAssignmentsResponse() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + reservation.SearchAllAssignmentsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.search_all_assignments( + parent="parent_value", query="query_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0].parent == "parent_value" + assert args[0].query == "query_value" + + +@pytest.mark.asyncio +async def test_search_all_assignments_flattened_error_async(): + client = ReservationServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.search_all_assignments( + reservation.SearchAllAssignmentsRequest(), + parent="parent_value", + query="query_value", + ) + + +def test_search_all_assignments_pager(): + client = ReservationServiceClient(credentials=ga_credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.search_all_assignments), "__call__" + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + reservation.SearchAllAssignmentsResponse( + assignments=[ + reservation.Assignment(), + reservation.Assignment(), + reservation.Assignment(), + ], + next_page_token="abc", + ), + reservation.SearchAllAssignmentsResponse( + assignments=[], next_page_token="def", + ), + reservation.SearchAllAssignmentsResponse( + assignments=[reservation.Assignment(),], next_page_token="ghi", + ), + reservation.SearchAllAssignmentsResponse( + assignments=[reservation.Assignment(), reservation.Assignment(),], + ), + RuntimeError, + ) + + metadata = () + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", ""),)), + ) + pager = client.search_all_assignments(request={}) + + assert pager._metadata == metadata + + results = [i for i in pager] + assert len(results) == 6 + assert all(isinstance(i, reservation.Assignment) for i in results) + + +def test_search_all_assignments_pages(): + client = ReservationServiceClient(credentials=ga_credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.search_all_assignments), "__call__" + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + reservation.SearchAllAssignmentsResponse( + assignments=[ + reservation.Assignment(), + reservation.Assignment(), + reservation.Assignment(), + ], + next_page_token="abc", + ), + reservation.SearchAllAssignmentsResponse( + assignments=[], next_page_token="def", + ), + reservation.SearchAllAssignmentsResponse( + assignments=[reservation.Assignment(),], next_page_token="ghi", + ), + reservation.SearchAllAssignmentsResponse( + assignments=[reservation.Assignment(), reservation.Assignment(),], + ), + RuntimeError, + ) + pages = list(client.search_all_assignments(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_search_all_assignments_async_pager(): + client = ReservationServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials, + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.search_all_assignments), + "__call__", + new_callable=mock.AsyncMock, + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + reservation.SearchAllAssignmentsResponse( + assignments=[ + reservation.Assignment(), + reservation.Assignment(), + reservation.Assignment(), + ], + next_page_token="abc", + ), + reservation.SearchAllAssignmentsResponse( + assignments=[], next_page_token="def", + ), + reservation.SearchAllAssignmentsResponse( + assignments=[reservation.Assignment(),], next_page_token="ghi", + ), + reservation.SearchAllAssignmentsResponse( + assignments=[reservation.Assignment(), reservation.Assignment(),], + ), + RuntimeError, + ) + async_pager = await client.search_all_assignments(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, reservation.Assignment) for i in responses) + + +@pytest.mark.asyncio +async def test_search_all_assignments_async_pages(): + client = ReservationServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials, + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.search_all_assignments), + "__call__", + new_callable=mock.AsyncMock, + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + reservation.SearchAllAssignmentsResponse( + assignments=[ + reservation.Assignment(), + reservation.Assignment(), + reservation.Assignment(), + ], + next_page_token="abc", + ), + reservation.SearchAllAssignmentsResponse( + assignments=[], next_page_token="def", + ), + reservation.SearchAllAssignmentsResponse( + assignments=[reservation.Assignment(),], next_page_token="ghi", + ), + reservation.SearchAllAssignmentsResponse( + assignments=[reservation.Assignment(), reservation.Assignment(),], + ), + RuntimeError, + ) + pages = [] + async for page_ in (await client.search_all_assignments(request={})).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + def test_move_assignment( transport: str = "grpc", request_type=reservation.MoveAssignmentRequest ): @@ -5718,6 +6113,7 @@ def test_reservation_service_base_transport(): "list_assignments", "delete_assignment", "search_assignments", + "search_all_assignments", "move_assignment", "get_bi_reservation", "update_bi_reservation", @@ -6126,7 +6522,7 @@ def test_parse_assignment_path(): def test_bi_reservation_path(): project = "winkle" location = "nautilus" - expected = "projects/{project}/locations/{location}/bireservation".format( + expected = "projects/{project}/locations/{location}/biReservation".format( project=project, location=location, ) actual = ReservationServiceClient.bi_reservation_path(project, location)