diff --git a/packages/google-cloud-compute/docs/compute_v1/reservation_blocks.rst b/packages/google-cloud-compute/docs/compute_v1/reservation_blocks.rst new file mode 100644 index 000000000000..9fdebfe5f4d7 --- /dev/null +++ b/packages/google-cloud-compute/docs/compute_v1/reservation_blocks.rst @@ -0,0 +1,10 @@ +ReservationBlocks +----------------------------------- + +.. automodule:: google.cloud.compute_v1.services.reservation_blocks + :members: + :inherited-members: + +.. automodule:: google.cloud.compute_v1.services.reservation_blocks.pagers + :members: + :inherited-members: diff --git a/packages/google-cloud-compute/docs/compute_v1/services_.rst b/packages/google-cloud-compute/docs/compute_v1/services_.rst index 7af4b46084d9..a5bfcd526ef3 100644 --- a/packages/google-cloud-compute/docs/compute_v1/services_.rst +++ b/packages/google-cloud-compute/docs/compute_v1/services_.rst @@ -76,6 +76,7 @@ Services for Google Cloud Compute v1 API region_target_tcp_proxies region_url_maps region_zones + reservation_blocks reservations resource_policies routers diff --git a/packages/google-cloud-compute/google/cloud/compute/__init__.py b/packages/google-cloud-compute/google/cloud/compute/__init__.py index 2a83c2f1effa..9a6256c7d36f 100644 --- a/packages/google-cloud-compute/google/cloud/compute/__init__.py +++ b/packages/google-cloud-compute/google/cloud/compute/__init__.py @@ -189,6 +189,9 @@ from google.cloud.compute_v1.services.region_url_maps.client import RegionUrlMapsClient from google.cloud.compute_v1.services.region_zones.client import RegionZonesClient from google.cloud.compute_v1.services.regions.client import RegionsClient +from google.cloud.compute_v1.services.reservation_blocks.client import ( + ReservationBlocksClient, +) from google.cloud.compute_v1.services.reservations.client import ReservationsClient from google.cloud.compute_v1.services.resource_policies.client import ( ResourcePoliciesClient, @@ -696,6 +699,7 @@ GetRegionTargetHttpsProxyRequest, GetRegionTargetTcpProxyRequest, GetRegionUrlMapRequest, + GetReservationBlockRequest, GetReservationRequest, GetResourcePolicyRequest, GetRoutePolicyRouterRequest, @@ -741,6 +745,7 @@ GlobalOrganizationSetPolicyRequest, GlobalSetLabelsRequest, GlobalSetPolicyRequest, + GroupMaintenanceInfo, GRPCHealthCheck, GuestAttributes, GuestAttributesEntry, @@ -1074,6 +1079,7 @@ ListRegionTargetTcpProxiesRequest, ListRegionUrlMapsRequest, ListRegionZonesRequest, + ListReservationBlocksRequest, ListReservationsRequest, ListResourcePoliciesRequest, ListRoutePoliciesRoutersRequest, @@ -1268,6 +1274,8 @@ PathRule, PerformMaintenanceInstanceRequest, PerformMaintenanceNodeGroupRequest, + PerformMaintenanceReservationBlockRequest, + PerformMaintenanceReservationRequest, PerInstanceConfig, Policy, PreconfiguredWafSet, @@ -1358,7 +1366,13 @@ Reservation, ReservationAffinity, ReservationAggregatedList, + ReservationBlock, + ReservationBlockPhysicalTopology, + ReservationBlocksGetResponse, + ReservationBlocksListResponse, ReservationList, + ReservationsBlocksPerformMaintenanceRequest, + ReservationsPerformMaintenanceRequest, ReservationsResizeRequest, ReservationsScopedList, ResetInstanceRequest, @@ -1413,6 +1427,7 @@ RouterNatRule, RouterNatRuleAction, RouterNatSubnetworkToNat, + RouterNatSubnetworkToNat64, RoutersGetRoutePolicyResponse, RoutersListBgpRoutes, RoutersListRoutePolicies, @@ -1526,6 +1541,7 @@ SetLabelsInstantSnapshotRequest, SetLabelsInterconnectAttachmentRequest, SetLabelsInterconnectRequest, + SetLabelsMachineImageRequest, SetLabelsRegionDiskRequest, SetLabelsRegionInstantSnapshotRequest, SetLabelsRegionSecurityPolicyRequest, @@ -1872,6 +1888,7 @@ "RegionTargetTcpProxiesClient", "RegionUrlMapsClient", "RegionZonesClient", + "ReservationBlocksClient", "ReservationsClient", "ResourcePoliciesClient", "RoutersClient", @@ -2352,6 +2369,7 @@ "GetRegionTargetHttpsProxyRequest", "GetRegionTargetTcpProxyRequest", "GetRegionUrlMapRequest", + "GetReservationBlockRequest", "GetReservationRequest", "GetResourcePolicyRequest", "GetRoutePolicyRouterRequest", @@ -2397,6 +2415,7 @@ "GlobalOrganizationSetPolicyRequest", "GlobalSetLabelsRequest", "GlobalSetPolicyRequest", + "GroupMaintenanceInfo", "GRPCHealthCheck", "GuestAttributes", "GuestAttributesEntry", @@ -2730,6 +2749,7 @@ "ListRegionTargetTcpProxiesRequest", "ListRegionUrlMapsRequest", "ListRegionZonesRequest", + "ListReservationBlocksRequest", "ListReservationsRequest", "ListResourcePoliciesRequest", "ListRoutePoliciesRoutersRequest", @@ -2924,6 +2944,8 @@ "PathRule", "PerformMaintenanceInstanceRequest", "PerformMaintenanceNodeGroupRequest", + "PerformMaintenanceReservationBlockRequest", + "PerformMaintenanceReservationRequest", "PerInstanceConfig", "Policy", "PreconfiguredWafSet", @@ -3014,7 +3036,13 @@ "Reservation", "ReservationAffinity", "ReservationAggregatedList", + "ReservationBlock", + "ReservationBlockPhysicalTopology", + "ReservationBlocksGetResponse", + "ReservationBlocksListResponse", "ReservationList", + "ReservationsBlocksPerformMaintenanceRequest", + "ReservationsPerformMaintenanceRequest", "ReservationsResizeRequest", "ReservationsScopedList", "ResetInstanceRequest", @@ -3069,6 +3097,7 @@ "RouterNatRule", "RouterNatRuleAction", "RouterNatSubnetworkToNat", + "RouterNatSubnetworkToNat64", "RoutersGetRoutePolicyResponse", "RoutersListBgpRoutes", "RoutersListRoutePolicies", @@ -3182,6 +3211,7 @@ "SetLabelsInstantSnapshotRequest", "SetLabelsInterconnectAttachmentRequest", "SetLabelsInterconnectRequest", + "SetLabelsMachineImageRequest", "SetLabelsRegionDiskRequest", "SetLabelsRegionInstantSnapshotRequest", "SetLabelsRegionSecurityPolicyRequest", diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/__init__.py b/packages/google-cloud-compute/google/cloud/compute_v1/__init__.py index 98e6f713b684..959b920a51a1 100644 --- a/packages/google-cloud-compute/google/cloud/compute_v1/__init__.py +++ b/packages/google-cloud-compute/google/cloud/compute_v1/__init__.py @@ -97,6 +97,7 @@ from .services.region_url_maps import RegionUrlMapsClient from .services.region_zones import RegionZonesClient from .services.regions import RegionsClient +from .services.reservation_blocks import ReservationBlocksClient from .services.reservations import ReservationsClient from .services.resource_policies import ResourcePoliciesClient from .services.routers import RoutersClient @@ -578,6 +579,7 @@ GetRegionTargetHttpsProxyRequest, GetRegionTargetTcpProxyRequest, GetRegionUrlMapRequest, + GetReservationBlockRequest, GetReservationRequest, GetResourcePolicyRequest, GetRoutePolicyRouterRequest, @@ -623,6 +625,7 @@ GlobalOrganizationSetPolicyRequest, GlobalSetLabelsRequest, GlobalSetPolicyRequest, + GroupMaintenanceInfo, GRPCHealthCheck, GuestAttributes, GuestAttributesEntry, @@ -956,6 +959,7 @@ ListRegionTargetTcpProxiesRequest, ListRegionUrlMapsRequest, ListRegionZonesRequest, + ListReservationBlocksRequest, ListReservationsRequest, ListResourcePoliciesRequest, ListRoutePoliciesRoutersRequest, @@ -1150,6 +1154,8 @@ PathRule, PerformMaintenanceInstanceRequest, PerformMaintenanceNodeGroupRequest, + PerformMaintenanceReservationBlockRequest, + PerformMaintenanceReservationRequest, PerInstanceConfig, Policy, PreconfiguredWafSet, @@ -1240,7 +1246,13 @@ Reservation, ReservationAffinity, ReservationAggregatedList, + ReservationBlock, + ReservationBlockPhysicalTopology, + ReservationBlocksGetResponse, + ReservationBlocksListResponse, ReservationList, + ReservationsBlocksPerformMaintenanceRequest, + ReservationsPerformMaintenanceRequest, ReservationsResizeRequest, ReservationsScopedList, ResetInstanceRequest, @@ -1295,6 +1307,7 @@ RouterNatRule, RouterNatRuleAction, RouterNatSubnetworkToNat, + RouterNatSubnetworkToNat64, RoutersGetRoutePolicyResponse, RoutersListBgpRoutes, RoutersListRoutePolicies, @@ -1408,6 +1421,7 @@ SetLabelsInstantSnapshotRequest, SetLabelsInterconnectAttachmentRequest, SetLabelsInterconnectRequest, + SetLabelsMachineImageRequest, SetLabelsRegionDiskRequest, SetLabelsRegionInstantSnapshotRequest, SetLabelsRegionSecurityPolicyRequest, @@ -2147,6 +2161,7 @@ "GetRegionTargetHttpsProxyRequest", "GetRegionTargetTcpProxyRequest", "GetRegionUrlMapRequest", + "GetReservationBlockRequest", "GetReservationRequest", "GetResourcePolicyRequest", "GetRoutePolicyRouterRequest", @@ -2198,6 +2213,7 @@ "GlobalPublicDelegatedPrefixesClient", "GlobalSetLabelsRequest", "GlobalSetPolicyRequest", + "GroupMaintenanceInfo", "GuestAttributes", "GuestAttributesEntry", "GuestAttributesValue", @@ -2546,6 +2562,7 @@ "ListRegionUrlMapsRequest", "ListRegionZonesRequest", "ListRegionsRequest", + "ListReservationBlocksRequest", "ListReservationsRequest", "ListResourcePoliciesRequest", "ListRoutePoliciesRoutersRequest", @@ -2753,6 +2770,8 @@ "PerInstanceConfig", "PerformMaintenanceInstanceRequest", "PerformMaintenanceNodeGroupRequest", + "PerformMaintenanceReservationBlockRequest", + "PerformMaintenanceReservationRequest", "Policy", "PreconfiguredWafSet", "PreservedState", @@ -2870,8 +2889,15 @@ "Reservation", "ReservationAffinity", "ReservationAggregatedList", + "ReservationBlock", + "ReservationBlockPhysicalTopology", + "ReservationBlocksClient", + "ReservationBlocksGetResponse", + "ReservationBlocksListResponse", "ReservationList", + "ReservationsBlocksPerformMaintenanceRequest", "ReservationsClient", + "ReservationsPerformMaintenanceRequest", "ReservationsResizeRequest", "ReservationsScopedList", "ResetInstanceRequest", @@ -2927,6 +2953,7 @@ "RouterNatRule", "RouterNatRuleAction", "RouterNatSubnetworkToNat", + "RouterNatSubnetworkToNat64", "RouterStatus", "RouterStatusBgpPeerStatus", "RouterStatusNatStatus", @@ -3045,6 +3072,7 @@ "SetLabelsInstantSnapshotRequest", "SetLabelsInterconnectAttachmentRequest", "SetLabelsInterconnectRequest", + "SetLabelsMachineImageRequest", "SetLabelsRegionDiskRequest", "SetLabelsRegionInstantSnapshotRequest", "SetLabelsRegionSecurityPolicyRequest", diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/gapic_metadata.json b/packages/google-cloud-compute/google/cloud/compute_v1/gapic_metadata.json index 62a1a2aa584d..58b63d85afc4 100644 --- a/packages/google-cloud-compute/google/cloud/compute_v1/gapic_metadata.json +++ b/packages/google-cloud-compute/google/cloud/compute_v1/gapic_metadata.json @@ -1787,6 +1787,11 @@ "set_iam_policy" ] }, + "SetLabels": { + "methods": [ + "set_labels" + ] + }, "TestIamPermissions": { "methods": [ "test_iam_permissions" @@ -3612,6 +3617,30 @@ } } }, + "ReservationBlocks": { + "clients": { + "rest": { + "libraryClient": "ReservationBlocksClient", + "rpcs": { + "Get": { + "methods": [ + "get" + ] + }, + "List": { + "methods": [ + "list" + ] + }, + "PerformMaintenance": { + "methods": [ + "perform_maintenance" + ] + } + } + } + } + }, "Reservations": { "clients": { "rest": { @@ -3647,6 +3676,11 @@ "list" ] }, + "PerformMaintenance": { + "methods": [ + "perform_maintenance" + ] + }, "Resize": { "methods": [ "resize" diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/client.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/client.py index 2ef06942f625..f717cf3b34ad 100644 --- a/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/client.py +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/client.py @@ -1773,6 +1773,302 @@ def sample_set_iam_policy(): # Done; return the response. return response + def set_labels_unary( + self, + request: Optional[Union[compute.SetLabelsMachineImageRequest, dict]] = None, + *, + project: Optional[str] = None, + resource: Optional[str] = None, + global_set_labels_request_resource: Optional[ + compute.GlobalSetLabelsRequest + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> compute.Operation: + r"""Sets the labels on a machine image. To learn more + about labels, read the Labeling Resources documentation. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import compute_v1 + + def sample_set_labels(): + # Create a client + client = compute_v1.MachineImagesClient() + + # Initialize request argument(s) + request = compute_v1.SetLabelsMachineImageRequest( + project="project_value", + resource="resource_value", + ) + + # Make the request + response = client.set_labels(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.compute_v1.types.SetLabelsMachineImageRequest, dict]): + The request object. A request message for + MachineImages.SetLabels. See the method + description for details. + project (str): + Project ID for this request. + This corresponds to the ``project`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource (str): + Name or id of the resource for this + request. + + This corresponds to the ``resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + global_set_labels_request_resource (google.cloud.compute_v1.types.GlobalSetLabelsRequest): + The body resource for this request + This corresponds to the ``global_set_labels_request_resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.api_core.extended_operation.ExtendedOperation: + An object representing a extended + long-running operation. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [project, resource, global_set_labels_request_resource] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + 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." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, compute.SetLabelsMachineImageRequest): + request = compute.SetLabelsMachineImageRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if project is not None: + request.project = project + if resource is not None: + request.resource = resource + if global_set_labels_request_resource is not None: + request.global_set_labels_request_resource = ( + global_set_labels_request_resource + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.set_labels] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ("project", request.project), + ("resource", request.resource), + ) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def set_labels( + self, + request: Optional[Union[compute.SetLabelsMachineImageRequest, dict]] = None, + *, + project: Optional[str] = None, + resource: Optional[str] = None, + global_set_labels_request_resource: Optional[ + compute.GlobalSetLabelsRequest + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> extended_operation.ExtendedOperation: + r"""Sets the labels on a machine image. To learn more + about labels, read the Labeling Resources documentation. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import compute_v1 + + def sample_set_labels(): + # Create a client + client = compute_v1.MachineImagesClient() + + # Initialize request argument(s) + request = compute_v1.SetLabelsMachineImageRequest( + project="project_value", + resource="resource_value", + ) + + # Make the request + response = client.set_labels(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.compute_v1.types.SetLabelsMachineImageRequest, dict]): + The request object. A request message for + MachineImages.SetLabels. See the method + description for details. + project (str): + Project ID for this request. + This corresponds to the ``project`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource (str): + Name or id of the resource for this + request. + + This corresponds to the ``resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + global_set_labels_request_resource (google.cloud.compute_v1.types.GlobalSetLabelsRequest): + The body resource for this request + This corresponds to the ``global_set_labels_request_resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.api_core.extended_operation.ExtendedOperation: + An object representing a extended + long-running operation. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [project, resource, global_set_labels_request_resource] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + 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." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, compute.SetLabelsMachineImageRequest): + request = compute.SetLabelsMachineImageRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if project is not None: + request.project = project + if resource is not None: + request.resource = resource + if global_set_labels_request_resource is not None: + request.global_set_labels_request_resource = ( + global_set_labels_request_resource + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.set_labels] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ("project", request.project), + ("resource", request.resource), + ) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + operation_service = self._transport._global_operations_client + operation_request = compute.GetGlobalOperationRequest() + operation_request.project = request.project + operation_request.operation = response.name + + get_operation = functools.partial(operation_service.get, operation_request) + # Cancel is not part of extended operations yet. + cancel_operation = lambda: None + + # Note: this class is an implementation detail to provide a uniform + # set of names for certain fields in the extended operation proto message. + # See google.api_core.extended_operation.ExtendedOperation for details + # on these properties and the expected interface. + class _CustomOperation(extended_operation.ExtendedOperation): + @property + def error_message(self): + return self._extended_operation.http_error_message + + @property + def error_code(self): + return self._extended_operation.http_error_status_code + + response = _CustomOperation.make(get_operation, cancel_operation, response) + + # Done; return the response. + return response + def test_iam_permissions( self, request: Optional[ diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/transports/base.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/transports/base.py index 91e52da7e5ec..706f10cc5a89 100644 --- a/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/transports/base.py +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/transports/base.py @@ -163,6 +163,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.set_labels: gapic_v1.method.wrap_method( + self.set_labels, + default_timeout=None, + client_info=client_info, + ), self.test_iam_permissions: gapic_v1.method.wrap_method( self.test_iam_permissions, default_timeout=None, @@ -233,6 +238,15 @@ def set_iam_policy( ]: raise NotImplementedError() + @property + def set_labels( + self, + ) -> Callable[ + [compute.SetLabelsMachineImageRequest], + Union[compute.Operation, Awaitable[compute.Operation]], + ]: + raise NotImplementedError() + @property def test_iam_permissions( self, diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/transports/rest.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/transports/rest.py index 67a3598e447d..62f77e267be6 100644 --- a/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/transports/rest.py +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/transports/rest.py @@ -116,6 +116,14 @@ def post_set_iam_policy(self, response): logging.log(f"Received response: {response}") return response + def pre_set_labels(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_set_labels(self, response): + logging.log(f"Received response: {response}") + return response + def pre_test_iam_permissions(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -404,6 +412,52 @@ def post_set_iam_policy_with_metadata( """ return response, metadata + def pre_set_labels( + self, + request: compute.SetLabelsMachineImageRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + compute.SetLabelsMachineImageRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for set_labels + + Override in a subclass to manipulate the request or metadata + before they are sent to the MachineImages server. + """ + return request, metadata + + def post_set_labels(self, response: compute.Operation) -> compute.Operation: + """Post-rpc interceptor for set_labels + + DEPRECATED. Please use the `post_set_labels_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the MachineImages server but before + it is returned to user code. This `post_set_labels` interceptor runs + before the `post_set_labels_with_metadata` interceptor. + """ + return response + + def post_set_labels_with_metadata( + self, + response: compute.Operation, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[compute.Operation, Sequence[Tuple[str, Union[str, bytes]]]]: + """Post-rpc interceptor for set_labels + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the MachineImages server but before it is returned to user code. + + We recommend only using this `post_set_labels_with_metadata` + interceptor in new development instead of the `post_set_labels` interceptor. + When both interceptors are used, this `post_set_labels_with_metadata` interceptor runs after the + `post_set_labels` interceptor. The (possibly modified) response returned by + `post_set_labels` will be passed to + `post_set_labels_with_metadata`. + """ + return response, metadata + def pre_test_iam_permissions( self, request: compute.TestIamPermissionsMachineImageRequest, @@ -1522,6 +1576,181 @@ def __call__( ) return resp + class _SetLabels( + _BaseMachineImagesRestTransport._BaseSetLabels, MachineImagesRestStub + ): + def __hash__(self): + return hash("MachineImagesRestTransport.SetLabels") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + return response + + def __call__( + self, + request: compute.SetLabelsMachineImageRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> compute.Operation: + r"""Call the set labels method over HTTP. + + Args: + request (~.compute.SetLabelsMachineImageRequest): + The request object. A request message for + MachineImages.SetLabels. See the method + description for details. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.compute.Operation: + Represents an Operation resource. Google Compute Engine + has three Operation resources: \* + `Global `__ + \* + `Regional `__ + \* + `Zonal `__ + You can use an operation resource to manage asynchronous + API requests. For more information, read Handling API + responses. Operations can be global, regional or zonal. + - For global operations, use the ``globalOperations`` + resource. - For regional operations, use the + ``regionOperations`` resource. - For zonal operations, + use the ``zoneOperations`` resource. For more + information, read Global, Regional, and Zonal Resources. + Note that completed Operation resources have a limited + retention period. + + """ + + http_options = ( + _BaseMachineImagesRestTransport._BaseSetLabels._get_http_options() + ) + + request, metadata = self._interceptor.pre_set_labels(request, metadata) + transcoded_request = ( + _BaseMachineImagesRestTransport._BaseSetLabels._get_transcoded_request( + http_options, request + ) + ) + + body = ( + _BaseMachineImagesRestTransport._BaseSetLabels._get_request_body_json( + transcoded_request + ) + ) + + # Jsonify the query params + query_params = ( + _BaseMachineImagesRestTransport._BaseSetLabels._get_query_params_json( + transcoded_request + ) + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.compute_v1.MachineImagesClient.SetLabels", + extra={ + "serviceName": "google.cloud.compute.v1.MachineImages", + "rpcName": "SetLabels", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = MachineImagesRestTransport._SetLabels._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = compute.Operation() + pb_resp = compute.Operation.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_set_labels(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_set_labels_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = compute.Operation.to_json(response) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.compute_v1.MachineImagesClient.set_labels", + extra={ + "serviceName": "google.cloud.compute.v1.MachineImages", + "rpcName": "SetLabels", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + class _TestIamPermissions( _BaseMachineImagesRestTransport._BaseTestIamPermissions, MachineImagesRestStub ): @@ -1722,6 +1951,14 @@ def set_iam_policy( # In C++ this would require a dynamic_cast return self._SetIamPolicy(self._session, self._host, self._interceptor) # type: ignore + @property + def set_labels( + self, + ) -> Callable[[compute.SetLabelsMachineImageRequest], compute.Operation]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._SetLabels(self._session, self._host, self._interceptor) # type: ignore + @property def test_iam_permissions( self, diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/transports/rest_base.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/transports/rest_base.py index 93887c6b328b..5930361f5c13 100644 --- a/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/transports/rest_base.py +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/machine_images/transports/rest_base.py @@ -383,6 +383,62 @@ def _get_query_params_json(transcoded_request): return query_params + class _BaseSetLabels: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/compute/v1/projects/{project}/global/machineImages/{resource}/setLabels", + "body": "global_set_labels_request_resource", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = compute.SetLabelsMachineImageRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_request_body_json(transcoded_request): + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=False + ) + return body + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=False, + ) + ) + query_params.update( + _BaseMachineImagesRestTransport._BaseSetLabels._get_unset_required_fields( + query_params + ) + ) + + return query_params + class _BaseTestIamPermissions: def __hash__(self): # pragma: NO COVER return NotImplementedError("__hash__ must be implemented.") diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/__init__.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/__init__.py new file mode 100644 index 000000000000..7db963207373 --- /dev/null +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ReservationBlocksClient + +__all__ = ("ReservationBlocksClient",) diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/client.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/client.py new file mode 100644 index 000000000000..9371f012786b --- /dev/null +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/client.py @@ -0,0 +1,1381 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Callable, + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import extended_operation, gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.compute_v1 import gapic_version as package_version + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = std_logging.getLogger(__name__) + +from google.api_core import extended_operation # type: ignore + +from google.cloud.compute_v1.services.reservation_blocks import pagers +from google.cloud.compute_v1.types import compute + +from .transports.base import DEFAULT_CLIENT_INFO, ReservationBlocksTransport +from .transports.rest import ReservationBlocksRestTransport + + +class ReservationBlocksClientMeta(type): + """Metaclass for the ReservationBlocks 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[ReservationBlocksTransport]] + _transport_registry["rest"] = ReservationBlocksRestTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ReservationBlocksTransport]: + """Returns 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 ReservationBlocksClient(metaclass=ReservationBlocksClientMeta): + """The ReservationBlocks API.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts 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") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "compute.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "compute.{UNIVERSE_DOMAIN}" + _DEFAULT_UNIVERSE = "googleapis.com" + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ReservationBlocksClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_info(info) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + @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: + ReservationBlocksClient: 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 + + @property + def transport(self) -> ReservationBlocksTransport: + """Returns the transport used by the client instance. + + Returns: + ReservationBlocksTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def common_billing_account_path( + billing_account: str, + ) -> str: + """Returns a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path( + folder: str, + ) -> str: + """Returns a fully-qualified folder string.""" + return "folders/{folder}".format( + folder=folder, + ) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path( + organization: str, + ) -> str: + """Returns a fully-qualified organization string.""" + return "organizations/{organization}".format( + organization=organization, + ) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path( + project: str, + ) -> str: + """Returns a fully-qualified project string.""" + return "projects/{project}".format( + project=project, + ) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path( + project: str, + location: str, + ) -> str: + """Returns a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, + location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[client_options_lib.ClientOptions] = None + ): + """Deprecated. Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + + warnings.warn( + "get_mtls_endpoint_and_cert_source is deprecated. Use the api_endpoint property instead.", + DeprecationWarning, + ) + if client_options is None: + client_options = client_options_lib.ClientOptions() + use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_client_cert not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + if use_mtls_endpoint not in ("auto", "never", "always"): + raise MutualTLSChannelError( + "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Figure out the client cert source to use. + client_cert_source = None + if use_client_cert == "true": + if client_options.client_cert_source: + client_cert_source = client_options.client_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + api_endpoint = cls.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = cls.DEFAULT_ENDPOINT + + return api_endpoint, client_cert_source + + @staticmethod + def _read_environment_variables(): + """Returns the environment variables used by the client. + + Returns: + Tuple[bool, str, str]: returns the GOOGLE_API_USE_CLIENT_CERTIFICATE, + GOOGLE_API_USE_MTLS_ENDPOINT, and GOOGLE_CLOUD_UNIVERSE_DOMAIN environment variables. + + Raises: + ValueError: If GOOGLE_API_USE_CLIENT_CERTIFICATE is not + any of ["true", "false"]. + google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT + is not any of ["auto", "never", "always"]. + """ + use_client_cert = os.getenv( + "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false" + ).lower() + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower() + universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN") + if use_client_cert not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + if use_mtls_endpoint not in ("auto", "never", "always"): + raise MutualTLSChannelError( + "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + return use_client_cert == "true", use_mtls_endpoint, universe_domain_env + + @staticmethod + def _get_client_cert_source(provided_cert_source, use_cert_flag): + """Return the client cert source to be used by the client. + + Args: + provided_cert_source (bytes): The client certificate source provided. + use_cert_flag (bool): A flag indicating whether to use the client certificate. + + Returns: + bytes or None: The client cert source to be used by the client. + """ + client_cert_source = None + if use_cert_flag: + if provided_cert_source: + client_cert_source = provided_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + return client_cert_source + + @staticmethod + def _get_api_endpoint( + api_override, client_cert_source, universe_domain, use_mtls_endpoint + ): + """Return the API endpoint used by the client. + + Args: + api_override (str): The API endpoint override. If specified, this is always + the return value of this function and the other arguments are not used. + client_cert_source (bytes): The client certificate source used by the client. + universe_domain (str): The universe domain used by the client. + use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters. + Possible values are "always", "auto", or "never". + + Returns: + str: The API endpoint to be used by the client. + """ + if api_override is not None: + api_endpoint = api_override + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + _default_universe = ReservationBlocksClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ReservationBlocksClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ReservationBlocksClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=universe_domain + ) + return api_endpoint + + @staticmethod + def _get_universe_domain( + client_universe_domain: Optional[str], universe_domain_env: Optional[str] + ) -> str: + """Return the universe domain used by the client. + + Args: + client_universe_domain (Optional[str]): The universe domain configured via the client options. + universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable. + + Returns: + str: The universe domain to be used by the client. + + Raises: + ValueError: If the universe domain is an empty string. + """ + universe_domain = ReservationBlocksClient._DEFAULT_UNIVERSE + if client_universe_domain is not None: + universe_domain = client_universe_domain + elif universe_domain_env is not None: + universe_domain = universe_domain_env + if len(universe_domain.strip()) == 0: + raise ValueError("Universe Domain cannot be an empty string.") + return universe_domain + + def _validate_universe_domain(self): + """Validates client's and credentials' universe domains are consistent. + + Returns: + bool: True iff the configured universe domain is valid. + + Raises: + ValueError: If the configured universe domain is not valid. + """ + + # NOTE (b/349488459): universe validation is disabled until further notice. + return True + + def _add_cred_info_for_auth_errors( + self, error: core_exceptions.GoogleAPICallError + ) -> None: + """Adds credential info string to error details for 401/403/404 errors. + + Args: + error (google.api_core.exceptions.GoogleAPICallError): The error to add the cred info. + """ + if error.code not in [ + HTTPStatus.UNAUTHORIZED, + HTTPStatus.FORBIDDEN, + HTTPStatus.NOT_FOUND, + ]: + return + + cred = self._transport._credentials + + # get_cred_info is only available in google-auth>=2.35.0 + if not hasattr(cred, "get_cred_info"): + return + + # ignore the type check since pypy test fails when get_cred_info + # is not available + cred_info = cred.get_cred_info() # type: ignore + if cred_info and hasattr(error._details, "append"): + error._details.append(json.dumps(cred_info)) + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used by the client instance. + """ + return self._universe_domain + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ReservationBlocksTransport, + Callable[..., ReservationBlocksTransport], + ] + ] = None, + client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the reservation blocks 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 (Optional[Union[str,ReservationBlocksTransport,Callable[..., ReservationBlocksTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the ReservationBlocksTransport constructor. + If set to None, a transport is chosen automatically. + NOTE: "rest" transport functionality is currently in a + beta state (preview). We welcome your feedback via an + issue in this library's source repository. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that the ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client_options = client_options + if isinstance(self._client_options, dict): + self._client_options = client_options_lib.from_dict(self._client_options) + if self._client_options is None: + self._client_options = client_options_lib.ClientOptions() + self._client_options = cast( + client_options_lib.ClientOptions, self._client_options + ) + + universe_domain_opt = getattr(self._client_options, "universe_domain", None) + + ( + self._use_client_cert, + self._use_mtls_endpoint, + self._universe_domain_env, + ) = ReservationBlocksClient._read_environment_variables() + self._client_cert_source = ReservationBlocksClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = ReservationBlocksClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + if CLIENT_LOGGING_SUPPORTED: # pragma: NO COVER + # Setup logging. + client_logging.initialize_logging() + + api_key_value = getattr(self._client_options, "api_key", None) + if api_key_value and credentials: + raise ValueError( + "client_options.api_key and credentials are mutually exclusive" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + transport_provided = isinstance(transport, ReservationBlocksTransport) + if transport_provided: + # transport is a ReservationBlocksTransport instance. + if credentials or self._client_options.credentials_file or api_key_value: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if self._client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = cast(ReservationBlocksTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ReservationBlocksClient._get_api_endpoint( + self._client_options.api_endpoint, + self._client_cert_source, + self._universe_domain, + self._use_mtls_endpoint, + ) + ) + + if not transport_provided: + import google.auth._default # type: ignore + + if api_key_value and hasattr( + google.auth._default, "get_api_key_credentials" + ): + credentials = google.auth._default.get_api_key_credentials( + api_key_value + ) + + transport_init: Union[ + Type[ReservationBlocksTransport], + Callable[..., ReservationBlocksTransport], + ] = ( + ReservationBlocksClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., ReservationBlocksTransport], transport) + ) + # initialize with the provided callable or the passed in class + self._transport = transport_init( + credentials=credentials, + credentials_file=self._client_options.credentials_file, + host=self._api_endpoint, + scopes=self._client_options.scopes, + client_cert_source_for_mtls=self._client_cert_source, + quota_project_id=self._client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + api_audience=self._client_options.api_audience, + ) + + if "async" not in str(self._transport): + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + std_logging.DEBUG + ): # pragma: NO COVER + _LOGGER.debug( + "Created client `google.cloud.compute_v1.ReservationBlocksClient`.", + extra={ + "serviceName": "google.cloud.compute.v1.ReservationBlocks", + "universeDomain": getattr( + self._transport._credentials, "universe_domain", "" + ), + "credentialsType": f"{type(self._transport._credentials).__module__}.{type(self._transport._credentials).__qualname__}", + "credentialsInfo": getattr( + self.transport._credentials, "get_cred_info", lambda: None + )(), + } + if hasattr(self._transport, "_credentials") + else { + "serviceName": "google.cloud.compute.v1.ReservationBlocks", + "credentialsType": None, + }, + ) + + def get( + self, + request: Optional[Union[compute.GetReservationBlockRequest, dict]] = None, + *, + project: Optional[str] = None, + zone: Optional[str] = None, + reservation: Optional[str] = None, + reservation_block: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> compute.ReservationBlocksGetResponse: + r"""Retrieves information about the specified reservation + block. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import compute_v1 + + def sample_get(): + # Create a client + client = compute_v1.ReservationBlocksClient() + + # Initialize request argument(s) + request = compute_v1.GetReservationBlockRequest( + project="project_value", + reservation="reservation_value", + reservation_block="reservation_block_value", + zone="zone_value", + ) + + # Make the request + response = client.get(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.compute_v1.types.GetReservationBlockRequest, dict]): + The request object. A request message for + ReservationBlocks.Get. See the method + description for details. + project (str): + Project ID for this request. + This corresponds to the ``project`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + zone (str): + Name of the zone for this request. + Zone name should conform to RFC1035. + + This corresponds to the ``zone`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + reservation (str): + The name of the reservation. Name + should conform to RFC1035 or be a + resource ID. + + This corresponds to the ``reservation`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + reservation_block (str): + The name of the reservation block. + Name should conform to RFC1035 or be a + resource ID. + + This corresponds to the ``reservation_block`` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.compute_v1.types.ReservationBlocksGetResponse: + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [project, zone, reservation, reservation_block] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + 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." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, compute.GetReservationBlockRequest): + request = compute.GetReservationBlockRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if project is not None: + request.project = project + if zone is not None: + request.zone = zone + if reservation is not None: + request.reservation = reservation + if reservation_block is not None: + request.reservation_block = reservation_block + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.get] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ("project", request.project), + ("zone", request.zone), + ("reservation", request.reservation), + ("reservation_block", request.reservation_block), + ) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def list( + self, + request: Optional[Union[compute.ListReservationBlocksRequest, dict]] = None, + *, + project: Optional[str] = None, + zone: Optional[str] = None, + reservation: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> pagers.ListPager: + r"""Retrieves a list of reservation blocks under a single + reservation. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import compute_v1 + + def sample_list(): + # Create a client + client = compute_v1.ReservationBlocksClient() + + # Initialize request argument(s) + request = compute_v1.ListReservationBlocksRequest( + project="project_value", + reservation="reservation_value", + zone="zone_value", + ) + + # Make the request + page_result = client.list(request=request) + + # Handle the response + for response in page_result: + print(response) + + Args: + request (Union[google.cloud.compute_v1.types.ListReservationBlocksRequest, dict]): + The request object. A request message for + ReservationBlocks.List. See the method + description for details. + project (str): + Project ID for this request. + This corresponds to the ``project`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + zone (str): + Name of the zone for this request. + Zone name should conform to RFC1035. + + This corresponds to the ``zone`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + reservation (str): + The name of the reservation. Name + should conform to RFC1035 or be a + resource ID. + + This corresponds to the ``reservation`` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.compute_v1.services.reservation_blocks.pagers.ListPager: + A list of reservation blocks under a + single reservation. + Iterating over this object will yield + results and resolve additional pages + automatically. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [project, zone, reservation] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + 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." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, compute.ListReservationBlocksRequest): + request = compute.ListReservationBlocksRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if project is not None: + request.project = project + if zone is not None: + request.zone = zone + if reservation is not None: + request.reservation = reservation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.list] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ("project", request.project), + ("zone", request.zone), + ("reservation", request.reservation), + ) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # 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.ListPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def perform_maintenance_unary( + self, + request: Optional[ + Union[compute.PerformMaintenanceReservationBlockRequest, dict] + ] = None, + *, + project: Optional[str] = None, + zone: Optional[str] = None, + reservation: Optional[str] = None, + reservation_block: Optional[str] = None, + reservations_blocks_perform_maintenance_request_resource: Optional[ + compute.ReservationsBlocksPerformMaintenanceRequest + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> compute.Operation: + r"""Allows customers to perform maintenance on a + reservation block + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import compute_v1 + + def sample_perform_maintenance(): + # Create a client + client = compute_v1.ReservationBlocksClient() + + # Initialize request argument(s) + request = compute_v1.PerformMaintenanceReservationBlockRequest( + project="project_value", + reservation="reservation_value", + reservation_block="reservation_block_value", + zone="zone_value", + ) + + # Make the request + response = client.perform_maintenance(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.compute_v1.types.PerformMaintenanceReservationBlockRequest, dict]): + The request object. A request message for + ReservationBlocks.PerformMaintenance. + See the method description for details. + project (str): + Project ID for this request. + This corresponds to the ``project`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + zone (str): + Name of the zone for this request. + Zone name should conform to RFC1035. + + This corresponds to the ``zone`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + reservation (str): + The name of the reservation. Name + should conform to RFC1035 or be a + resource ID. + + This corresponds to the ``reservation`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + reservation_block (str): + The name of the reservation block. + Name should conform to RFC1035 or be a + resource ID. + + This corresponds to the ``reservation_block`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + reservations_blocks_perform_maintenance_request_resource (google.cloud.compute_v1.types.ReservationsBlocksPerformMaintenanceRequest): + The body resource for this request + This corresponds to the ``reservations_blocks_perform_maintenance_request_resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.api_core.extended_operation.ExtendedOperation: + An object representing a extended + long-running operation. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [ + project, + zone, + reservation, + reservation_block, + reservations_blocks_perform_maintenance_request_resource, + ] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + 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." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, compute.PerformMaintenanceReservationBlockRequest): + request = compute.PerformMaintenanceReservationBlockRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if project is not None: + request.project = project + if zone is not None: + request.zone = zone + if reservation is not None: + request.reservation = reservation + if reservation_block is not None: + request.reservation_block = reservation_block + if reservations_blocks_perform_maintenance_request_resource is not None: + request.reservations_blocks_perform_maintenance_request_resource = ( + reservations_blocks_perform_maintenance_request_resource + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.perform_maintenance] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ("project", request.project), + ("zone", request.zone), + ("reservation", request.reservation), + ("reservation_block", request.reservation_block), + ) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def perform_maintenance( + self, + request: Optional[ + Union[compute.PerformMaintenanceReservationBlockRequest, dict] + ] = None, + *, + project: Optional[str] = None, + zone: Optional[str] = None, + reservation: Optional[str] = None, + reservation_block: Optional[str] = None, + reservations_blocks_perform_maintenance_request_resource: Optional[ + compute.ReservationsBlocksPerformMaintenanceRequest + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> extended_operation.ExtendedOperation: + r"""Allows customers to perform maintenance on a + reservation block + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import compute_v1 + + def sample_perform_maintenance(): + # Create a client + client = compute_v1.ReservationBlocksClient() + + # Initialize request argument(s) + request = compute_v1.PerformMaintenanceReservationBlockRequest( + project="project_value", + reservation="reservation_value", + reservation_block="reservation_block_value", + zone="zone_value", + ) + + # Make the request + response = client.perform_maintenance(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.compute_v1.types.PerformMaintenanceReservationBlockRequest, dict]): + The request object. A request message for + ReservationBlocks.PerformMaintenance. + See the method description for details. + project (str): + Project ID for this request. + This corresponds to the ``project`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + zone (str): + Name of the zone for this request. + Zone name should conform to RFC1035. + + This corresponds to the ``zone`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + reservation (str): + The name of the reservation. Name + should conform to RFC1035 or be a + resource ID. + + This corresponds to the ``reservation`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + reservation_block (str): + The name of the reservation block. + Name should conform to RFC1035 or be a + resource ID. + + This corresponds to the ``reservation_block`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + reservations_blocks_perform_maintenance_request_resource (google.cloud.compute_v1.types.ReservationsBlocksPerformMaintenanceRequest): + The body resource for this request + This corresponds to the ``reservations_blocks_perform_maintenance_request_resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.api_core.extended_operation.ExtendedOperation: + An object representing a extended + long-running operation. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [ + project, + zone, + reservation, + reservation_block, + reservations_blocks_perform_maintenance_request_resource, + ] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + 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." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, compute.PerformMaintenanceReservationBlockRequest): + request = compute.PerformMaintenanceReservationBlockRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if project is not None: + request.project = project + if zone is not None: + request.zone = zone + if reservation is not None: + request.reservation = reservation + if reservation_block is not None: + request.reservation_block = reservation_block + if reservations_blocks_perform_maintenance_request_resource is not None: + request.reservations_blocks_perform_maintenance_request_resource = ( + reservations_blocks_perform_maintenance_request_resource + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.perform_maintenance] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ("project", request.project), + ("zone", request.zone), + ("reservation", request.reservation), + ("reservation_block", request.reservation_block), + ) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + operation_service = self._transport._zone_operations_client + operation_request = compute.GetZoneOperationRequest() + operation_request.project = request.project + operation_request.zone = request.zone + operation_request.operation = response.name + + get_operation = functools.partial(operation_service.get, operation_request) + # Cancel is not part of extended operations yet. + cancel_operation = lambda: None + + # Note: this class is an implementation detail to provide a uniform + # set of names for certain fields in the extended operation proto message. + # See google.api_core.extended_operation.ExtendedOperation for details + # on these properties and the expected interface. + class _CustomOperation(extended_operation.ExtendedOperation): + @property + def error_message(self): + return self._extended_operation.http_error_message + + @property + def error_code(self): + return self._extended_operation.http_error_status_code + + response = _CustomOperation.make(get_operation, cancel_operation, response) + + # Done; return the response. + return response + + def __enter__(self) -> "ReservationBlocksClient": + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +__all__ = ("ReservationBlocksClient",) diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/pagers.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/pagers.py new file mode 100644 index 000000000000..6b51006f1730 --- /dev/null +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/pagers.py @@ -0,0 +1,117 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, + AsyncIterator, + Awaitable, + Callable, + Iterator, + Optional, + Sequence, + Tuple, + Union, +) + +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import retry_async as retries_async + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] + OptionalAsyncRetry = Union[ + retries_async.AsyncRetry, gapic_v1.method._MethodDefault, None + ] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + OptionalAsyncRetry = Union[retries_async.AsyncRetry, object, None] # type: ignore + +from google.cloud.compute_v1.types import compute + + +class ListPager: + """A pager for iterating through ``list`` requests. + + This class thinly wraps an initial + :class:`google.cloud.compute_v1.types.ReservationBlocksListResponse` object, and + provides an ``__iter__`` method to iterate through its + ``items`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``List`` requests and continue to iterate + through the ``items`` field on the + corresponding responses. + + All the usual :class:`google.cloud.compute_v1.types.ReservationBlocksListResponse` + 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[..., compute.ReservationBlocksListResponse], + request: compute.ListReservationBlocksRequest, + response: compute.ReservationBlocksListResponse, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = () + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.compute_v1.types.ListReservationBlocksRequest): + The initial request object. + response (google.cloud.compute_v1.types.ReservationBlocksListResponse): + The initial response object. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + """ + self._method = method + self._request = compute.ListReservationBlocksRequest(request) + self._response = response + self._retry = retry + self._timeout = timeout + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages(self) -> Iterator[compute.ReservationBlocksListResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = self._method( + self._request, + retry=self._retry, + timeout=self._timeout, + metadata=self._metadata, + ) + yield self._response + + def __iter__(self) -> Iterator[compute.ReservationBlock]: + for page in self.pages: + yield from page.items + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/transports/README.rst b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/transports/README.rst new file mode 100644 index 000000000000..ead61ffe03c8 --- /dev/null +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ReservationBlocksTransport` is the ABC for all transports. +- public child `ReservationBlocksGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ReservationBlocksGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseReservationBlocksRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ReservationBlocksRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/transports/__init__.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/transports/__init__.py new file mode 100644 index 000000000000..dac223f2446f --- /dev/null +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 ReservationBlocksTransport +from .rest import ReservationBlocksRestInterceptor, ReservationBlocksRestTransport + +# Compile a registry of transports. +_transport_registry = OrderedDict() # type: Dict[str, Type[ReservationBlocksTransport]] +_transport_registry["rest"] = ReservationBlocksRestTransport + +__all__ = ( + "ReservationBlocksTransport", + "ReservationBlocksRestTransport", + "ReservationBlocksRestInterceptor", +) diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/transports/base.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/transports/base.py new file mode 100644 index 000000000000..9800277f6612 --- /dev/null +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/transports/base.py @@ -0,0 +1,212 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Awaitable, Callable, Dict, Optional, Sequence, Union + +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.compute_v1 import gapic_version as package_version +from google.cloud.compute_v1.services import zone_operations +from google.cloud.compute_v1.types import compute + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +class ReservationBlocksTransport(abc.ABC): + """Abstract transport class for ReservationBlocks.""" + + AUTH_SCOPES = ( + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/cloud-platform", + ) + + DEFAULT_HOST: str = "compute.googleapis.com" + + def __init__( + self, + *, + host: str = DEFAULT_HOST, + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'compute.googleapis.com'). + 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. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + self._extended_operations_services: Dict[str, Any] = {} + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, **scopes_kwargs, quota_project_id=quota_project_id + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.get: gapic_v1.method.wrap_method( + self.get, + default_timeout=None, + client_info=client_info, + ), + self.list: gapic_v1.method.wrap_method( + self.list, + default_timeout=None, + client_info=client_info, + ), + self.perform_maintenance: gapic_v1.method.wrap_method( + self.perform_maintenance, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + + @property + def get( + self, + ) -> Callable[ + [compute.GetReservationBlockRequest], + Union[ + compute.ReservationBlocksGetResponse, + Awaitable[compute.ReservationBlocksGetResponse], + ], + ]: + raise NotImplementedError() + + @property + def list( + self, + ) -> Callable[ + [compute.ListReservationBlocksRequest], + Union[ + compute.ReservationBlocksListResponse, + Awaitable[compute.ReservationBlocksListResponse], + ], + ]: + raise NotImplementedError() + + @property + def perform_maintenance( + self, + ) -> Callable[ + [compute.PerformMaintenanceReservationBlockRequest], + Union[compute.Operation, Awaitable[compute.Operation]], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + @property + def _zone_operations_client(self) -> zone_operations.ZoneOperationsClient: + ex_op_service = self._extended_operations_services.get("zone_operations") + if not ex_op_service: + ex_op_service = zone_operations.ZoneOperationsClient( + credentials=self._credentials, + transport=self.kind, + ) + self._extended_operations_services["zone_operations"] = ex_op_service + + return ex_op_service + + +__all__ = ("ReservationBlocksTransport",) diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/transports/rest.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/transports/rest.py new file mode 100644 index 000000000000..5637f3726fd0 --- /dev/null +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/transports/rest.py @@ -0,0 +1,851 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 dataclasses +import json # type: ignore +import logging +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1, rest_helpers, rest_streaming +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.requests import AuthorizedSession # type: ignore +from google.protobuf import json_format +from requests import __version__ as requests_version + +from google.cloud.compute_v1.types import compute + +from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO +from .rest_base import _BaseReservationBlocksRestTransport + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = logging.getLogger(__name__) + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version, + grpc_version=None, + rest_version=f"requests@{requests_version}", +) + + +class ReservationBlocksRestInterceptor: + """Interceptor for ReservationBlocks. + + Interceptors are used to manipulate requests, request metadata, and responses + in arbitrary ways. + Example use cases include: + * Logging + * Verifying requests according to service or custom semantics + * Stripping extraneous information from responses + + These use cases and more can be enabled by injecting an + instance of a custom subclass when constructing the ReservationBlocksRestTransport. + + .. code-block:: python + class MyCustomReservationBlocksInterceptor(ReservationBlocksRestInterceptor): + def pre_get(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_list(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_list(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_perform_maintenance(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_perform_maintenance(self, response): + logging.log(f"Received response: {response}") + return response + + transport = ReservationBlocksRestTransport(interceptor=MyCustomReservationBlocksInterceptor()) + client = ReservationBlocksClient(transport=transport) + + + """ + + def pre_get( + self, + request: compute.GetReservationBlockRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + compute.GetReservationBlockRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for get + + Override in a subclass to manipulate the request or metadata + before they are sent to the ReservationBlocks server. + """ + return request, metadata + + def post_get( + self, response: compute.ReservationBlocksGetResponse + ) -> compute.ReservationBlocksGetResponse: + """Post-rpc interceptor for get + + DEPRECATED. Please use the `post_get_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the ReservationBlocks server but before + it is returned to user code. This `post_get` interceptor runs + before the `post_get_with_metadata` interceptor. + """ + return response + + def post_get_with_metadata( + self, + response: compute.ReservationBlocksGetResponse, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + compute.ReservationBlocksGetResponse, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Post-rpc interceptor for get + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the ReservationBlocks server but before it is returned to user code. + + We recommend only using this `post_get_with_metadata` + interceptor in new development instead of the `post_get` interceptor. + When both interceptors are used, this `post_get_with_metadata` interceptor runs after the + `post_get` interceptor. The (possibly modified) response returned by + `post_get` will be passed to + `post_get_with_metadata`. + """ + return response, metadata + + def pre_list( + self, + request: compute.ListReservationBlocksRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + compute.ListReservationBlocksRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for list + + Override in a subclass to manipulate the request or metadata + before they are sent to the ReservationBlocks server. + """ + return request, metadata + + def post_list( + self, response: compute.ReservationBlocksListResponse + ) -> compute.ReservationBlocksListResponse: + """Post-rpc interceptor for list + + DEPRECATED. Please use the `post_list_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the ReservationBlocks server but before + it is returned to user code. This `post_list` interceptor runs + before the `post_list_with_metadata` interceptor. + """ + return response + + def post_list_with_metadata( + self, + response: compute.ReservationBlocksListResponse, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + compute.ReservationBlocksListResponse, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Post-rpc interceptor for list + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the ReservationBlocks server but before it is returned to user code. + + We recommend only using this `post_list_with_metadata` + interceptor in new development instead of the `post_list` interceptor. + When both interceptors are used, this `post_list_with_metadata` interceptor runs after the + `post_list` interceptor. The (possibly modified) response returned by + `post_list` will be passed to + `post_list_with_metadata`. + """ + return response, metadata + + def pre_perform_maintenance( + self, + request: compute.PerformMaintenanceReservationBlockRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + compute.PerformMaintenanceReservationBlockRequest, + Sequence[Tuple[str, Union[str, bytes]]], + ]: + """Pre-rpc interceptor for perform_maintenance + + Override in a subclass to manipulate the request or metadata + before they are sent to the ReservationBlocks server. + """ + return request, metadata + + def post_perform_maintenance( + self, response: compute.Operation + ) -> compute.Operation: + """Post-rpc interceptor for perform_maintenance + + DEPRECATED. Please use the `post_perform_maintenance_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the ReservationBlocks server but before + it is returned to user code. This `post_perform_maintenance` interceptor runs + before the `post_perform_maintenance_with_metadata` interceptor. + """ + return response + + def post_perform_maintenance_with_metadata( + self, + response: compute.Operation, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[compute.Operation, Sequence[Tuple[str, Union[str, bytes]]]]: + """Post-rpc interceptor for perform_maintenance + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the ReservationBlocks server but before it is returned to user code. + + We recommend only using this `post_perform_maintenance_with_metadata` + interceptor in new development instead of the `post_perform_maintenance` interceptor. + When both interceptors are used, this `post_perform_maintenance_with_metadata` interceptor runs after the + `post_perform_maintenance` interceptor. The (possibly modified) response returned by + `post_perform_maintenance` will be passed to + `post_perform_maintenance_with_metadata`. + """ + return response, metadata + + +@dataclasses.dataclass +class ReservationBlocksRestStub: + _session: AuthorizedSession + _host: str + _interceptor: ReservationBlocksRestInterceptor + + +class ReservationBlocksRestTransport(_BaseReservationBlocksRestTransport): + """REST backend synchronous transport for ReservationBlocks. + + The ReservationBlocks API. + + 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 JSON representations of protocol buffers over HTTP/1.1 + """ + + def __init__( + self, + *, + host: str = "compute.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + url_scheme: str = "https", + interceptor: Optional[ReservationBlocksRestInterceptor] = None, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + NOTE: This REST transport functionality is currently in a beta + state (preview). We welcome your feedback via a GitHub issue in + this library's repository. Thank you! + + Args: + host (Optional[str]): + The hostname to connect to (default: 'compute.googleapis.com'). + 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 ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + client_cert_source_for_mtls (Callable[[], Tuple[bytes, bytes]]): Client + certificate to configure mutual TLS HTTP channel. It is ignored + if ``channel`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you are developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + url_scheme: the protocol scheme for the API endpoint. Normally + "https", but for testing or local servers, + "http" can be specified. + """ + # Run the base constructor + # TODO(yon-mg): resolve other ctor params i.e. scopes, quota, etc. + # TODO: When custom host (api_endpoint) is set, `scopes` must *also* be set on the + # credentials object + super().__init__( + host=host, + credentials=credentials, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + url_scheme=url_scheme, + api_audience=api_audience, + ) + self._session = AuthorizedSession( + self._credentials, default_host=self.DEFAULT_HOST + ) + if client_cert_source_for_mtls: + self._session.configure_mtls_channel(client_cert_source_for_mtls) + self._interceptor = interceptor or ReservationBlocksRestInterceptor() + self._prep_wrapped_messages(client_info) + + class _Get(_BaseReservationBlocksRestTransport._BaseGet, ReservationBlocksRestStub): + def __hash__(self): + return hash("ReservationBlocksRestTransport.Get") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + return response + + def __call__( + self, + request: compute.GetReservationBlockRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> compute.ReservationBlocksGetResponse: + r"""Call the get method over HTTP. + + Args: + request (~.compute.GetReservationBlockRequest): + The request object. A request message for + ReservationBlocks.Get. See the method + description for details. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.compute.ReservationBlocksGetResponse: + + """ + + http_options = ( + _BaseReservationBlocksRestTransport._BaseGet._get_http_options() + ) + + request, metadata = self._interceptor.pre_get(request, metadata) + transcoded_request = ( + _BaseReservationBlocksRestTransport._BaseGet._get_transcoded_request( + http_options, request + ) + ) + + # Jsonify the query params + query_params = ( + _BaseReservationBlocksRestTransport._BaseGet._get_query_params_json( + transcoded_request + ) + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.compute_v1.ReservationBlocksClient.Get", + extra={ + "serviceName": "google.cloud.compute.v1.ReservationBlocks", + "rpcName": "Get", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = ReservationBlocksRestTransport._Get._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = compute.ReservationBlocksGetResponse() + pb_resp = compute.ReservationBlocksGetResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_get(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_get_with_metadata(resp, response_metadata) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = compute.ReservationBlocksGetResponse.to_json( + response + ) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.compute_v1.ReservationBlocksClient.get", + extra={ + "serviceName": "google.cloud.compute.v1.ReservationBlocks", + "rpcName": "Get", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + + class _List( + _BaseReservationBlocksRestTransport._BaseList, ReservationBlocksRestStub + ): + def __hash__(self): + return hash("ReservationBlocksRestTransport.List") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + return response + + def __call__( + self, + request: compute.ListReservationBlocksRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> compute.ReservationBlocksListResponse: + r"""Call the list method over HTTP. + + Args: + request (~.compute.ListReservationBlocksRequest): + The request object. A request message for + ReservationBlocks.List. See the method + description for details. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.compute.ReservationBlocksListResponse: + A list of reservation blocks under a + single reservation. + + """ + + http_options = ( + _BaseReservationBlocksRestTransport._BaseList._get_http_options() + ) + + request, metadata = self._interceptor.pre_list(request, metadata) + transcoded_request = ( + _BaseReservationBlocksRestTransport._BaseList._get_transcoded_request( + http_options, request + ) + ) + + # Jsonify the query params + query_params = ( + _BaseReservationBlocksRestTransport._BaseList._get_query_params_json( + transcoded_request + ) + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.compute_v1.ReservationBlocksClient.List", + extra={ + "serviceName": "google.cloud.compute.v1.ReservationBlocks", + "rpcName": "List", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = ReservationBlocksRestTransport._List._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = compute.ReservationBlocksListResponse() + pb_resp = compute.ReservationBlocksListResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_list(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_list_with_metadata(resp, response_metadata) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = compute.ReservationBlocksListResponse.to_json( + response + ) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.compute_v1.ReservationBlocksClient.list", + extra={ + "serviceName": "google.cloud.compute.v1.ReservationBlocks", + "rpcName": "List", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + + class _PerformMaintenance( + _BaseReservationBlocksRestTransport._BasePerformMaintenance, + ReservationBlocksRestStub, + ): + def __hash__(self): + return hash("ReservationBlocksRestTransport.PerformMaintenance") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + return response + + def __call__( + self, + request: compute.PerformMaintenanceReservationBlockRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> compute.Operation: + r"""Call the perform maintenance method over HTTP. + + Args: + request (~.compute.PerformMaintenanceReservationBlockRequest): + The request object. A request message for + ReservationBlocks.PerformMaintenance. + See the method description for details. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.compute.Operation: + Represents an Operation resource. Google Compute Engine + has three Operation resources: \* + `Global `__ + \* + `Regional `__ + \* + `Zonal `__ + You can use an operation resource to manage asynchronous + API requests. For more information, read Handling API + responses. Operations can be global, regional or zonal. + - For global operations, use the ``globalOperations`` + resource. - For regional operations, use the + ``regionOperations`` resource. - For zonal operations, + use the ``zoneOperations`` resource. For more + information, read Global, Regional, and Zonal Resources. + Note that completed Operation resources have a limited + retention period. + + """ + + http_options = ( + _BaseReservationBlocksRestTransport._BasePerformMaintenance._get_http_options() + ) + + request, metadata = self._interceptor.pre_perform_maintenance( + request, metadata + ) + transcoded_request = _BaseReservationBlocksRestTransport._BasePerformMaintenance._get_transcoded_request( + http_options, request + ) + + body = _BaseReservationBlocksRestTransport._BasePerformMaintenance._get_request_body_json( + transcoded_request + ) + + # Jsonify the query params + query_params = _BaseReservationBlocksRestTransport._BasePerformMaintenance._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.compute_v1.ReservationBlocksClient.PerformMaintenance", + extra={ + "serviceName": "google.cloud.compute.v1.ReservationBlocks", + "rpcName": "PerformMaintenance", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = ReservationBlocksRestTransport._PerformMaintenance._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = compute.Operation() + pb_resp = compute.Operation.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_perform_maintenance(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_perform_maintenance_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = compute.Operation.to_json(response) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.compute_v1.ReservationBlocksClient.perform_maintenance", + extra={ + "serviceName": "google.cloud.compute.v1.ReservationBlocks", + "rpcName": "PerformMaintenance", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + + @property + def get( + self, + ) -> Callable[ + [compute.GetReservationBlockRequest], compute.ReservationBlocksGetResponse + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._Get(self._session, self._host, self._interceptor) # type: ignore + + @property + def list( + self, + ) -> Callable[ + [compute.ListReservationBlocksRequest], compute.ReservationBlocksListResponse + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._List(self._session, self._host, self._interceptor) # type: ignore + + @property + def perform_maintenance( + self, + ) -> Callable[ + [compute.PerformMaintenanceReservationBlockRequest], compute.Operation + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._PerformMaintenance(self._session, self._host, self._interceptor) # type: ignore + + @property + def kind(self) -> str: + return "rest" + + def close(self): + self._session.close() + + +__all__ = ("ReservationBlocksRestTransport",) diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/transports/rest_base.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/transports/rest_base.py new file mode 100644 index 000000000000..55f15c26f066 --- /dev/null +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservation_blocks/transports/rest_base.py @@ -0,0 +1,239 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 json # type: ignore +import re +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1, path_template +from google.protobuf import json_format + +from google.cloud.compute_v1.types import compute + +from .base import DEFAULT_CLIENT_INFO, ReservationBlocksTransport + + +class _BaseReservationBlocksRestTransport(ReservationBlocksTransport): + """Base REST backend transport for ReservationBlocks. + + Note: This class is not meant to be used directly. Use its sync and + async sub-classes instead. + + 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 JSON representations of protocol buffers over HTTP/1.1 + """ + + def __init__( + self, + *, + host: str = "compute.googleapis.com", + credentials: Optional[Any] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + url_scheme: str = "https", + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + Args: + host (Optional[str]): + The hostname to connect to (default: 'compute.googleapis.com'). + credentials (Optional[Any]): 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. + 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 are developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + url_scheme: the protocol scheme for the API endpoint. Normally + "https", but for testing or local servers, + "http" can be specified. + """ + # Run the base constructor + maybe_url_match = re.match("^(?Phttp(?:s)?://)?(?P.*)$", host) + if maybe_url_match is None: + raise ValueError( + f"Unexpected hostname structure: {host}" + ) # pragma: NO COVER + + url_match_items = maybe_url_match.groupdict() + + host = f"{url_scheme}://{host}" if not url_match_items["scheme"] else host + + super().__init__( + host=host, + credentials=credentials, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + class _BaseGet: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/compute/v1/projects/{project}/zones/{zone}/reservations/{reservation}/reservationBlocks/{reservation_block}", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = compute.GetReservationBlockRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=False, + ) + ) + query_params.update( + _BaseReservationBlocksRestTransport._BaseGet._get_unset_required_fields( + query_params + ) + ) + + return query_params + + class _BaseList: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/compute/v1/projects/{project}/zones/{zone}/reservations/{reservation}/reservationBlocks", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = compute.ListReservationBlocksRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=False, + ) + ) + query_params.update( + _BaseReservationBlocksRestTransport._BaseList._get_unset_required_fields( + query_params + ) + ) + + return query_params + + class _BasePerformMaintenance: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/compute/v1/projects/{project}/zones/{zone}/reservations/{reservation}/reservationBlocks/{reservation_block}/performMaintenance", + "body": "reservations_blocks_perform_maintenance_request_resource", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = compute.PerformMaintenanceReservationBlockRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_request_body_json(transcoded_request): + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=False + ) + return body + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=False, + ) + ) + query_params.update( + _BaseReservationBlocksRestTransport._BasePerformMaintenance._get_unset_required_fields( + query_params + ) + ) + + return query_params + + +__all__ = ("_BaseReservationBlocksRestTransport",) diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/client.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/client.py index 93fe904954d3..3ab47e89c994 100644 --- a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/client.py +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/client.py @@ -1809,6 +1809,341 @@ def sample_list(): # Done; return the response. return response + def perform_maintenance_unary( + self, + request: Optional[ + Union[compute.PerformMaintenanceReservationRequest, dict] + ] = None, + *, + project: Optional[str] = None, + zone: Optional[str] = None, + reservation: Optional[str] = None, + reservations_perform_maintenance_request_resource: Optional[ + compute.ReservationsPerformMaintenanceRequest + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> compute.Operation: + r"""Perform maintenance on an extended reservation + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import compute_v1 + + def sample_perform_maintenance(): + # Create a client + client = compute_v1.ReservationsClient() + + # Initialize request argument(s) + request = compute_v1.PerformMaintenanceReservationRequest( + project="project_value", + reservation="reservation_value", + zone="zone_value", + ) + + # Make the request + response = client.perform_maintenance(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.compute_v1.types.PerformMaintenanceReservationRequest, dict]): + The request object. A request message for + Reservations.PerformMaintenance. See the + method description for details. + project (str): + Project ID for this request. + This corresponds to the ``project`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + zone (str): + Name of the zone for this request. + Zone name should conform to RFC1035. + + This corresponds to the ``zone`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + reservation (str): + The name of the reservation. Name + should conform to RFC1035 or be a + resource ID. + + This corresponds to the ``reservation`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + reservations_perform_maintenance_request_resource (google.cloud.compute_v1.types.ReservationsPerformMaintenanceRequest): + The body resource for this request + This corresponds to the ``reservations_perform_maintenance_request_resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.api_core.extended_operation.ExtendedOperation: + An object representing a extended + long-running operation. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [ + project, + zone, + reservation, + reservations_perform_maintenance_request_resource, + ] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + 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." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, compute.PerformMaintenanceReservationRequest): + request = compute.PerformMaintenanceReservationRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if project is not None: + request.project = project + if zone is not None: + request.zone = zone + if reservation is not None: + request.reservation = reservation + if reservations_perform_maintenance_request_resource is not None: + request.reservations_perform_maintenance_request_resource = ( + reservations_perform_maintenance_request_resource + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.perform_maintenance] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ("project", request.project), + ("zone", request.zone), + ("reservation", request.reservation), + ) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def perform_maintenance( + self, + request: Optional[ + Union[compute.PerformMaintenanceReservationRequest, dict] + ] = None, + *, + project: Optional[str] = None, + zone: Optional[str] = None, + reservation: Optional[str] = None, + reservations_perform_maintenance_request_resource: Optional[ + compute.ReservationsPerformMaintenanceRequest + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> extended_operation.ExtendedOperation: + r"""Perform maintenance on an extended reservation + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import compute_v1 + + def sample_perform_maintenance(): + # Create a client + client = compute_v1.ReservationsClient() + + # Initialize request argument(s) + request = compute_v1.PerformMaintenanceReservationRequest( + project="project_value", + reservation="reservation_value", + zone="zone_value", + ) + + # Make the request + response = client.perform_maintenance(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.compute_v1.types.PerformMaintenanceReservationRequest, dict]): + The request object. A request message for + Reservations.PerformMaintenance. See the + method description for details. + project (str): + Project ID for this request. + This corresponds to the ``project`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + zone (str): + Name of the zone for this request. + Zone name should conform to RFC1035. + + This corresponds to the ``zone`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + reservation (str): + The name of the reservation. Name + should conform to RFC1035 or be a + resource ID. + + This corresponds to the ``reservation`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + reservations_perform_maintenance_request_resource (google.cloud.compute_v1.types.ReservationsPerformMaintenanceRequest): + The body resource for this request + This corresponds to the ``reservations_perform_maintenance_request_resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.api_core.extended_operation.ExtendedOperation: + An object representing a extended + long-running operation. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [ + project, + zone, + reservation, + reservations_perform_maintenance_request_resource, + ] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + 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." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, compute.PerformMaintenanceReservationRequest): + request = compute.PerformMaintenanceReservationRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if project is not None: + request.project = project + if zone is not None: + request.zone = zone + if reservation is not None: + request.reservation = reservation + if reservations_perform_maintenance_request_resource is not None: + request.reservations_perform_maintenance_request_resource = ( + reservations_perform_maintenance_request_resource + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.perform_maintenance] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ("project", request.project), + ("zone", request.zone), + ("reservation", request.reservation), + ) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + operation_service = self._transport._zone_operations_client + operation_request = compute.GetZoneOperationRequest() + operation_request.project = request.project + operation_request.zone = request.zone + operation_request.operation = response.name + + get_operation = functools.partial(operation_service.get, operation_request) + # Cancel is not part of extended operations yet. + cancel_operation = lambda: None + + # Note: this class is an implementation detail to provide a uniform + # set of names for certain fields in the extended operation proto message. + # See google.api_core.extended_operation.ExtendedOperation for details + # on these properties and the expected interface. + class _CustomOperation(extended_operation.ExtendedOperation): + @property + def error_message(self): + return self._extended_operation.http_error_message + + @property + def error_code(self): + return self._extended_operation.http_error_status_code + + response = _CustomOperation.make(get_operation, cancel_operation, response) + + # Done; return the response. + return response + def resize_unary( self, request: Optional[Union[compute.ResizeReservationRequest, dict]] = None, diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/transports/base.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/transports/base.py index 4c20f1821367..4eafe78be6ac 100644 --- a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/transports/base.py +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/transports/base.py @@ -163,6 +163,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.perform_maintenance: gapic_v1.method.wrap_method( + self.perform_maintenance, + default_timeout=None, + client_info=client_info, + ), self.resize: gapic_v1.method.wrap_method( self.resize, default_timeout=None, @@ -251,6 +256,15 @@ def list( ]: raise NotImplementedError() + @property + def perform_maintenance( + self, + ) -> Callable[ + [compute.PerformMaintenanceReservationRequest], + Union[compute.Operation, Awaitable[compute.Operation]], + ]: + raise NotImplementedError() + @property def resize( self, diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/transports/rest.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/transports/rest.py index 4dfc1d814278..3e8860712320 100644 --- a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/transports/rest.py +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/transports/rest.py @@ -116,6 +116,14 @@ def post_list(self, response): logging.log(f"Received response: {response}") return response + def pre_perform_maintenance(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_perform_maintenance(self, response): + logging.log(f"Received response: {response}") + return response + def pre_resize(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -433,6 +441,55 @@ def post_list_with_metadata( """ return response, metadata + def pre_perform_maintenance( + self, + request: compute.PerformMaintenanceReservationRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + compute.PerformMaintenanceReservationRequest, + Sequence[Tuple[str, Union[str, bytes]]], + ]: + """Pre-rpc interceptor for perform_maintenance + + Override in a subclass to manipulate the request or metadata + before they are sent to the Reservations server. + """ + return request, metadata + + def post_perform_maintenance( + self, response: compute.Operation + ) -> compute.Operation: + """Post-rpc interceptor for perform_maintenance + + DEPRECATED. Please use the `post_perform_maintenance_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the Reservations server but before + it is returned to user code. This `post_perform_maintenance` interceptor runs + before the `post_perform_maintenance_with_metadata` interceptor. + """ + return response + + def post_perform_maintenance_with_metadata( + self, + response: compute.Operation, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[compute.Operation, Sequence[Tuple[str, Union[str, bytes]]]]: + """Post-rpc interceptor for perform_maintenance + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the Reservations server but before it is returned to user code. + + We recommend only using this `post_perform_maintenance_with_metadata` + interceptor in new development instead of the `post_perform_maintenance` interceptor. + When both interceptors are used, this `post_perform_maintenance_with_metadata` interceptor runs after the + `post_perform_maintenance` interceptor. The (possibly modified) response returned by + `post_perform_maintenance` will be passed to + `post_perform_maintenance_with_metadata`. + """ + return response, metadata + def pre_resize( self, request: compute.ResizeReservationRequest, @@ -1662,6 +1719,177 @@ def __call__( ) return resp + class _PerformMaintenance( + _BaseReservationsRestTransport._BasePerformMaintenance, ReservationsRestStub + ): + def __hash__(self): + return hash("ReservationsRestTransport.PerformMaintenance") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + return response + + def __call__( + self, + request: compute.PerformMaintenanceReservationRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> compute.Operation: + r"""Call the perform maintenance method over HTTP. + + Args: + request (~.compute.PerformMaintenanceReservationRequest): + The request object. A request message for + Reservations.PerformMaintenance. See the + method description for details. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.compute.Operation: + Represents an Operation resource. Google Compute Engine + has three Operation resources: \* + `Global `__ + \* + `Regional `__ + \* + `Zonal `__ + You can use an operation resource to manage asynchronous + API requests. For more information, read Handling API + responses. Operations can be global, regional or zonal. + - For global operations, use the ``globalOperations`` + resource. - For regional operations, use the + ``regionOperations`` resource. - For zonal operations, + use the ``zoneOperations`` resource. For more + information, read Global, Regional, and Zonal Resources. + Note that completed Operation resources have a limited + retention period. + + """ + + http_options = ( + _BaseReservationsRestTransport._BasePerformMaintenance._get_http_options() + ) + + request, metadata = self._interceptor.pre_perform_maintenance( + request, metadata + ) + transcoded_request = _BaseReservationsRestTransport._BasePerformMaintenance._get_transcoded_request( + http_options, request + ) + + body = _BaseReservationsRestTransport._BasePerformMaintenance._get_request_body_json( + transcoded_request + ) + + # Jsonify the query params + query_params = _BaseReservationsRestTransport._BasePerformMaintenance._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.compute_v1.ReservationsClient.PerformMaintenance", + extra={ + "serviceName": "google.cloud.compute.v1.Reservations", + "rpcName": "PerformMaintenance", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = ReservationsRestTransport._PerformMaintenance._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = compute.Operation() + pb_resp = compute.Operation.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_perform_maintenance(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_perform_maintenance_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = compute.Operation.to_json(response) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.compute_v1.ReservationsClient.perform_maintenance", + extra={ + "serviceName": "google.cloud.compute.v1.Reservations", + "rpcName": "PerformMaintenance", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + class _Resize(_BaseReservationsRestTransport._BaseResize, ReservationsRestStub): def __hash__(self): return hash("ReservationsRestTransport.Resize") @@ -2381,6 +2609,14 @@ def list( # In C++ this would require a dynamic_cast return self._List(self._session, self._host, self._interceptor) # type: ignore + @property + def perform_maintenance( + self, + ) -> Callable[[compute.PerformMaintenanceReservationRequest], compute.Operation]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._PerformMaintenance(self._session, self._host, self._interceptor) # type: ignore + @property def resize(self) -> Callable[[compute.ResizeReservationRequest], compute.Operation]: # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/transports/rest_base.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/transports/rest_base.py index 619553c30f78..04c4a2179edb 100644 --- a/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/transports/rest_base.py +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/reservations/transports/rest_base.py @@ -373,6 +373,62 @@ def _get_query_params_json(transcoded_request): return query_params + class _BasePerformMaintenance: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/compute/v1/projects/{project}/zones/{zone}/reservations/{reservation}/performMaintenance", + "body": "reservations_perform_maintenance_request_resource", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = compute.PerformMaintenanceReservationRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_request_body_json(transcoded_request): + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=False + ) + return body + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=False, + ) + ) + query_params.update( + _BaseReservationsRestTransport._BasePerformMaintenance._get_unset_required_fields( + query_params + ) + ) + + return query_params + class _BaseResize: def __hash__(self): # pragma: NO COVER return NotImplementedError("__hash__ must be implemented.") diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/snapshots/client.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/snapshots/client.py index 3a86cbc5e24d..7dde52aca8d6 100644 --- a/packages/google-cloud-compute/google/cloud/compute_v1/services/snapshots/client.py +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/snapshots/client.py @@ -1035,7 +1035,7 @@ def sample_get(): resource. You can use snapshots to back up data on a regular interval. For more information, read Creating persistent - disk snapshots. + disk snapshots. LINT.IfChange """ # Create or coerce a protobuf request object. diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/services/snapshots/transports/rest.py b/packages/google-cloud-compute/google/cloud/compute_v1/services/snapshots/transports/rest.py index f8e80cc37982..1a95578f1d2e 100644 --- a/packages/google-cloud-compute/google/cloud/compute_v1/services/snapshots/transports/rest.py +++ b/packages/google-cloud-compute/google/cloud/compute_v1/services/snapshots/transports/rest.py @@ -811,7 +811,7 @@ def __call__( resource. You can use snapshots to back up data on a regular interval. For more information, read Creating persistent - disk snapshots. + disk snapshots. LINT.IfChange """ diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/types/__init__.py b/packages/google-cloud-compute/google/cloud/compute_v1/types/__init__.py index 9f33ce92b2aa..e2864d3cbdd7 100644 --- a/packages/google-cloud-compute/google/cloud/compute_v1/types/__init__.py +++ b/packages/google-cloud-compute/google/cloud/compute_v1/types/__init__.py @@ -468,6 +468,7 @@ GetRegionTargetHttpsProxyRequest, GetRegionTargetTcpProxyRequest, GetRegionUrlMapRequest, + GetReservationBlockRequest, GetReservationRequest, GetResourcePolicyRequest, GetRoutePolicyRouterRequest, @@ -513,6 +514,7 @@ GlobalOrganizationSetPolicyRequest, GlobalSetLabelsRequest, GlobalSetPolicyRequest, + GroupMaintenanceInfo, GRPCHealthCheck, GuestAttributes, GuestAttributesEntry, @@ -846,6 +848,7 @@ ListRegionTargetTcpProxiesRequest, ListRegionUrlMapsRequest, ListRegionZonesRequest, + ListReservationBlocksRequest, ListReservationsRequest, ListResourcePoliciesRequest, ListRoutePoliciesRoutersRequest, @@ -1040,6 +1043,8 @@ PathRule, PerformMaintenanceInstanceRequest, PerformMaintenanceNodeGroupRequest, + PerformMaintenanceReservationBlockRequest, + PerformMaintenanceReservationRequest, PerInstanceConfig, Policy, PreconfiguredWafSet, @@ -1130,7 +1135,13 @@ Reservation, ReservationAffinity, ReservationAggregatedList, + ReservationBlock, + ReservationBlockPhysicalTopology, + ReservationBlocksGetResponse, + ReservationBlocksListResponse, ReservationList, + ReservationsBlocksPerformMaintenanceRequest, + ReservationsPerformMaintenanceRequest, ReservationsResizeRequest, ReservationsScopedList, ResetInstanceRequest, @@ -1185,6 +1196,7 @@ RouterNatRule, RouterNatRuleAction, RouterNatSubnetworkToNat, + RouterNatSubnetworkToNat64, RoutersGetRoutePolicyResponse, RoutersListBgpRoutes, RoutersListRoutePolicies, @@ -1298,6 +1310,7 @@ SetLabelsInstantSnapshotRequest, SetLabelsInterconnectAttachmentRequest, SetLabelsInterconnectRequest, + SetLabelsMachineImageRequest, SetLabelsRegionDiskRequest, SetLabelsRegionInstantSnapshotRequest, SetLabelsRegionSecurityPolicyRequest, @@ -2025,6 +2038,7 @@ "GetRegionTargetHttpsProxyRequest", "GetRegionTargetTcpProxyRequest", "GetRegionUrlMapRequest", + "GetReservationBlockRequest", "GetReservationRequest", "GetResourcePolicyRequest", "GetRoutePolicyRouterRequest", @@ -2070,6 +2084,7 @@ "GlobalOrganizationSetPolicyRequest", "GlobalSetLabelsRequest", "GlobalSetPolicyRequest", + "GroupMaintenanceInfo", "GRPCHealthCheck", "GuestAttributes", "GuestAttributesEntry", @@ -2403,6 +2418,7 @@ "ListRegionTargetTcpProxiesRequest", "ListRegionUrlMapsRequest", "ListRegionZonesRequest", + "ListReservationBlocksRequest", "ListReservationsRequest", "ListResourcePoliciesRequest", "ListRoutePoliciesRoutersRequest", @@ -2597,6 +2613,8 @@ "PathRule", "PerformMaintenanceInstanceRequest", "PerformMaintenanceNodeGroupRequest", + "PerformMaintenanceReservationBlockRequest", + "PerformMaintenanceReservationRequest", "PerInstanceConfig", "Policy", "PreconfiguredWafSet", @@ -2687,7 +2705,13 @@ "Reservation", "ReservationAffinity", "ReservationAggregatedList", + "ReservationBlock", + "ReservationBlockPhysicalTopology", + "ReservationBlocksGetResponse", + "ReservationBlocksListResponse", "ReservationList", + "ReservationsBlocksPerformMaintenanceRequest", + "ReservationsPerformMaintenanceRequest", "ReservationsResizeRequest", "ReservationsScopedList", "ResetInstanceRequest", @@ -2742,6 +2766,7 @@ "RouterNatRule", "RouterNatRuleAction", "RouterNatSubnetworkToNat", + "RouterNatSubnetworkToNat64", "RoutersGetRoutePolicyResponse", "RoutersListBgpRoutes", "RoutersListRoutePolicies", @@ -2855,6 +2880,7 @@ "SetLabelsInstantSnapshotRequest", "SetLabelsInterconnectAttachmentRequest", "SetLabelsInterconnectRequest", + "SetLabelsMachineImageRequest", "SetLabelsRegionDiskRequest", "SetLabelsRegionInstantSnapshotRequest", "SetLabelsRegionSecurityPolicyRequest", diff --git a/packages/google-cloud-compute/google/cloud/compute_v1/types/compute.py b/packages/google-cloud-compute/google/cloud/compute_v1/types/compute.py index 21fc1b0fd1f7..9a25a216c586 100644 --- a/packages/google-cloud-compute/google/cloud/compute_v1/types/compute.py +++ b/packages/google-cloud-compute/google/cloud/compute_v1/types/compute.py @@ -478,6 +478,7 @@ "GetRegionTargetHttpsProxyRequest", "GetRegionTargetTcpProxyRequest", "GetRegionUrlMapRequest", + "GetReservationBlockRequest", "GetReservationRequest", "GetResourcePolicyRequest", "GetRoutePolicyRouterRequest", @@ -523,6 +524,7 @@ "GlobalOrganizationSetPolicyRequest", "GlobalSetLabelsRequest", "GlobalSetPolicyRequest", + "GroupMaintenanceInfo", "GuestAttributes", "GuestAttributesEntry", "GuestAttributesValue", @@ -855,6 +857,7 @@ "ListRegionUrlMapsRequest", "ListRegionZonesRequest", "ListRegionsRequest", + "ListReservationBlocksRequest", "ListReservationsRequest", "ListResourcePoliciesRequest", "ListRoutePoliciesRoutersRequest", @@ -1050,6 +1053,8 @@ "PerInstanceConfig", "PerformMaintenanceInstanceRequest", "PerformMaintenanceNodeGroupRequest", + "PerformMaintenanceReservationBlockRequest", + "PerformMaintenanceReservationRequest", "Policy", "PreconfiguredWafSet", "PreservedState", @@ -1139,7 +1144,13 @@ "Reservation", "ReservationAffinity", "ReservationAggregatedList", + "ReservationBlock", + "ReservationBlockPhysicalTopology", + "ReservationBlocksGetResponse", + "ReservationBlocksListResponse", "ReservationList", + "ReservationsBlocksPerformMaintenanceRequest", + "ReservationsPerformMaintenanceRequest", "ReservationsResizeRequest", "ReservationsScopedList", "ResetInstanceRequest", @@ -1194,6 +1205,7 @@ "RouterNatRule", "RouterNatRuleAction", "RouterNatSubnetworkToNat", + "RouterNatSubnetworkToNat64", "RouterStatus", "RouterStatusBgpPeerStatus", "RouterStatusNatStatus", @@ -1308,6 +1320,7 @@ "SetLabelsInstantSnapshotRequest", "SetLabelsInterconnectAttachmentRequest", "SetLabelsInterconnectRequest", + "SetLabelsMachineImageRequest", "SetLabelsRegionDiskRequest", "SetLabelsRegionInstantSnapshotRequest", "SetLabelsRegionSecurityPolicyRequest", @@ -11490,12 +11503,32 @@ class AllocationResourceStatus(proto.Message): .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields Attributes: + reservation_block_count (int): + The number of reservation blocks associated + with this reservation. + + This field is a member of `oneof`_ ``_reservation_block_count``. + reservation_maintenance (google.cloud.compute_v1.types.GroupMaintenanceInfo): + Maintenance information for this reservation + + This field is a member of `oneof`_ ``_reservation_maintenance``. specific_sku_allocation (google.cloud.compute_v1.types.AllocationResourceStatusSpecificSKUAllocation): Allocation Properties of this reservation. This field is a member of `oneof`_ ``_specific_sku_allocation``. """ + reservation_block_count: int = proto.Field( + proto.INT32, + number=161835754, + optional=True, + ) + reservation_maintenance: "GroupMaintenanceInfo" = proto.Field( + proto.MESSAGE, + number=340607776, + optional=True, + message="GroupMaintenanceInfo", + ) specific_sku_allocation: "AllocationResourceStatusSpecificSKUAllocation" = ( proto.Field( proto.MESSAGE, @@ -14608,7 +14641,7 @@ class BackendBucketCdnPolicy(proto.Message): default_ttl (int): Specifies the default TTL for cached content served by this origin for responses that do not have an existing valid TTL - (max-age or s-max-age). Setting a TTL of "0" means "always + (max-age or s-maxage). Setting a TTL of "0" means "always revalidate". The value of defaultTTL cannot be set to a value greater than that of maxTTL, but can be equal. When the cacheMode is set to FORCE_CACHE_ALL, the defaultTTL will @@ -14680,7 +14713,7 @@ class BackendBucketCdnPolicy(proto.Message): configured here will not be served. The default limit (max-stale) is 86400s (1 day), which will allow stale content to be served up to this - limit beyond the max-age (or s-max-age) of a + limit beyond the max-age (or s-maxage) of a cached response. The maximum allowed value is 604800 (1 week). Set this to zero (0) to disable serve-while-stale. @@ -15161,6 +15194,36 @@ class BackendService(proto.Message): Balancer. This field is a member of `oneof`_ ``_enable_c_d_n``. + external_managed_migration_state (str): + Specifies the canary migration state. Possible values are + PREPARE, TEST_BY_PERCENTAGE, and TEST_ALL_TRAFFIC. To begin + the migration from EXTERNAL to EXTERNAL_MANAGED, the state + must be changed to PREPARE. The state must be changed to + TEST_ALL_TRAFFIC before the loadBalancingScheme can be + changed to EXTERNAL_MANAGED. Optionally, the + TEST_BY_PERCENTAGE state can be used to migrate traffic by + percentage using externalManagedMigrationTestingPercentage. + Rolling back a migration requires the states to be set in + reverse order. So changing the scheme from EXTERNAL_MANAGED + to EXTERNAL requires the state to be set to TEST_ALL_TRAFFIC + at the same time. Optionally, the TEST_BY_PERCENTAGE state + can be used to migrate some traffic back to EXTERNAL or + PREPARE can be used to migrate all traffic back to EXTERNAL. + Check the ExternalManagedMigrationState enum for the list of + possible values. + + This field is a member of `oneof`_ ``_external_managed_migration_state``. + external_managed_migration_testing_percentage (float): + Determines the fraction of requests that should be processed + by the Global external Application Load Balancer. The value + of this field must be in the range [0, 100]. Session + affinity options will slightly affect this routing behavior, + for more details, see: Session Affinity. This value can only + be set if the loadBalancingScheme in the BackendService is + set to EXTERNAL (when using the classic Application Load + Balancer) and the migration state is TEST_BY_PERCENTAGE. + + This field is a member of `oneof`_ ``_external_managed_migration_testing_percentage``. failover_policy (google.cloud.compute_v1.types.BackendServiceFailoverPolicy): Requires at least one backend instance group to be defined as a backup (failover) backend. For load balancers that have @@ -15533,6 +15596,37 @@ class CompressionMode(proto.Enum): AUTOMATIC = 165298699 DISABLED = 516696700 + class ExternalManagedMigrationState(proto.Enum): + r"""Specifies the canary migration state. Possible values are PREPARE, + TEST_BY_PERCENTAGE, and TEST_ALL_TRAFFIC. To begin the migration + from EXTERNAL to EXTERNAL_MANAGED, the state must be changed to + PREPARE. The state must be changed to TEST_ALL_TRAFFIC before the + loadBalancingScheme can be changed to EXTERNAL_MANAGED. Optionally, + the TEST_BY_PERCENTAGE state can be used to migrate traffic by + percentage using externalManagedMigrationTestingPercentage. Rolling + back a migration requires the states to be set in reverse order. So + changing the scheme from EXTERNAL_MANAGED to EXTERNAL requires the + state to be set to TEST_ALL_TRAFFIC at the same time. Optionally, + the TEST_BY_PERCENTAGE state can be used to migrate some traffic + back to EXTERNAL or PREPARE can be used to migrate all traffic back + to EXTERNAL. + + Values: + UNDEFINED_EXTERNAL_MANAGED_MIGRATION_STATE (0): + A value indicating that the enum field is not + set. + PREPARE (399612135): + No description available. + TEST_ALL_TRAFFIC (79728882): + No description available. + TEST_BY_PERCENTAGE (513738389): + No description available. + """ + UNDEFINED_EXTERNAL_MANAGED_MIGRATION_STATE = 0 + PREPARE = 399612135 + TEST_ALL_TRAFFIC = 79728882 + TEST_BY_PERCENTAGE = 513738389 + class IpAddressSelectionPolicy(proto.Enum): r"""Specifies a preference for traffic sent from the proxy to the backend (or from the client to the backend for proxyless gRPC). The @@ -15923,6 +16017,16 @@ class SessionAffinity(proto.Enum): number=250733499, optional=True, ) + external_managed_migration_state: str = proto.Field( + proto.STRING, + number=66947020, + optional=True, + ) + external_managed_migration_testing_percentage: float = proto.Field( + proto.FLOAT, + number=507232462, + optional=True, + ) failover_policy: "BackendServiceFailoverPolicy" = proto.Field( proto.MESSAGE, number=105658655, @@ -16227,7 +16331,7 @@ class BackendServiceCdnPolicy(proto.Message): default_ttl (int): Specifies the default TTL for cached content served by this origin for responses that do not have an existing valid TTL - (max-age or s-max-age). Setting a TTL of "0" means "always + (max-age or s-maxage). Setting a TTL of "0" means "always revalidate". The value of defaultTTL cannot be set to a value greater than that of maxTTL, but can be equal. When the cacheMode is set to FORCE_CACHE_ALL, the defaultTTL will @@ -16299,7 +16403,7 @@ class BackendServiceCdnPolicy(proto.Message): configured here will not be served. The default limit (max-stale) is 86400s (1 day), which will allow stale content to be served up to this - limit beyond the max-age (or s-max-age) of a + limit beyond the max-age (or s-maxage) of a cached response. The maximum allowed value is 604800 (1 week). Set this to zero (0) to disable serve-while-stale. @@ -16854,12 +16958,12 @@ class BackendServiceHAPolicy(proto.Message): The maximum number of backend services with fastIPMove in a VPC in a region is 64. - The network endpoints that are attached to a backend of a backend service with fastIPMove - cannot resolve to C3 machines. - Traffic directed to the - leader by a static route next hop will not be redirected to - a new leader by fast failover. Such traffic will only be - redirected once an haPolicy.leader update has taken effect. - Only traffic to the forwarding rule's virtual IP will be - redirected to a new leader by fast failover. + cannot resolve to Gen3+ machines for IPv6. - Traffic + directed to the leader by a static route next hop will not + be redirected to a new leader by fast failover. Such traffic + will only be redirected once an haPolicy.leader update has + taken effect. Only traffic to the forwarding rule's virtual + IP will be redirected to a new leader by fast failover. haPolicy.fastIPMove can be set only at backend service creation time. Once set, it cannot be updated. By default, fastIpMove is set to DISABLED. Check the FastIPMove enum for @@ -16915,10 +17019,10 @@ class FastIPMove(proto.Enum): of its backends is 64. - The maximum number of backend services with fastIPMove in a VPC in a region is 64. - The network endpoints that are attached to a backend of a backend service with fastIPMove - cannot resolve to C3 machines. - Traffic directed to the leader by a - static route next hop will not be redirected to a new leader by fast - failover. Such traffic will only be redirected once an - haPolicy.leader update has taken effect. Only traffic to the + cannot resolve to Gen3+ machines for IPv6. - Traffic directed to the + leader by a static route next hop will not be redirected to a new + leader by fast failover. Such traffic will only be redirected once + an haPolicy.leader update has taken effect. Only traffic to the forwarding rule's virtual IP will be redirected to a new leader by fast failover. haPolicy.fastIPMove can be set only at backend service creation time. Once set, it cannot be updated. By default, @@ -18780,6 +18884,16 @@ class CacheInvalidationRule(proto.Message): .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields Attributes: + cache_tags (MutableSequence[str]): + A list of cache tags used to identify cached objects. - + Cache tags are specified when the response is first cached, + by setting the ``Cache-Tag`` response header at the origin. + - Multiple cache tags in the same invalidation request are + treated as Boolean ``OR`` - for example, + ``tag1 OR tag2 OR tag3``. - If other fields are also + specified, these are treated as Boolean ``AND`` with any + tags. Up to 10 tags can be specified in a single + invalidation request. host (str): If set, this invalidation rule will only apply to requests with a Host header matching @@ -18791,6 +18905,10 @@ class CacheInvalidationRule(proto.Message): This field is a member of `oneof`_ ``_path``. """ + cache_tags: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=29073078, + ) host: str = proto.Field( proto.STRING, number=3208616, @@ -19493,6 +19611,8 @@ class Type(proto.Enum): No description available. ACCELERATOR_OPTIMIZED_A3_ULTRA (27812811): No description available. + ACCELERATOR_OPTIMIZED_A4 (158574527): + No description available. COMPUTE_OPTIMIZED (158349023): No description available. COMPUTE_OPTIMIZED_C2D (383246453): @@ -19546,6 +19666,7 @@ class Type(proto.Enum): ACCELERATOR_OPTIMIZED_A3 = 158574526 ACCELERATOR_OPTIMIZED_A3_MEGA = 156517459 ACCELERATOR_OPTIMIZED_A3_ULTRA = 27812811 + ACCELERATOR_OPTIMIZED_A4 = 158574527 COMPUTE_OPTIMIZED = 158349023 COMPUTE_OPTIMIZED_C2D = 383246453 COMPUTE_OPTIMIZED_C3 = 428004784 @@ -34118,6 +34239,42 @@ class GetRegionUrlMapRequest(proto.Message): ) +class GetReservationBlockRequest(proto.Message): + r"""A request message for ReservationBlocks.Get. See the method + description for details. + + Attributes: + project (str): + Project ID for this request. + reservation (str): + The name of the reservation. Name should + conform to RFC1035 or be a resource ID. + reservation_block (str): + The name of the reservation block. Name + should conform to RFC1035 or be a resource ID. + zone (str): + Name of the zone for this request. Zone name + should conform to RFC1035. + """ + + project: str = proto.Field( + proto.STRING, + number=227560217, + ) + reservation: str = proto.Field( + proto.STRING, + number=47530956, + ) + reservation_block: str = proto.Field( + proto.STRING, + number=532832858, + ) + zone: str = proto.Field( + proto.STRING, + number=3744684, + ) + + class GetReservationRequest(proto.Message): r"""A request message for Reservations.Get. See the method description for details. @@ -35480,6 +35637,81 @@ class GlobalSetPolicyRequest(proto.Message): ) +class GroupMaintenanceInfo(proto.Message): + r"""Maintenance Info for ReservationBlocks. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + maintenance_ongoing_count (int): + Progress for ongoing maintenance for this + group of VMs/hosts. Describes number of hosts in + the block that have ongoing maintenance. + + This field is a member of `oneof`_ ``_maintenance_ongoing_count``. + maintenance_pending_count (int): + Progress for ongoing maintenance for this + group of VMs/hosts. Describes number of hosts in + the block that have pending maintenance. + + This field is a member of `oneof`_ ``_maintenance_pending_count``. + scheduling_type (str): + The type of maintenance for the reservation. + Check the SchedulingType enum for the list of + possible values. + + This field is a member of `oneof`_ ``_scheduling_type``. + upcoming_group_maintenance (google.cloud.compute_v1.types.UpcomingMaintenance): + Maintenance information on this group of VMs. + + This field is a member of `oneof`_ ``_upcoming_group_maintenance``. + """ + + class SchedulingType(proto.Enum): + r"""The type of maintenance for the reservation. + + Values: + UNDEFINED_SCHEDULING_TYPE (0): + A value indicating that the enum field is not + set. + GROUPED (474540862): + Maintenance on all reserved instances in the + reservation is synchronized. + GROUP_MAINTENANCE_TYPE_UNSPECIFIED (447183678): + Unknown maintenance type. + INDEPENDENT (127011674): + Maintenance is not synchronized for this + reservation. Instead, each instance has its own + maintenance window. + """ + UNDEFINED_SCHEDULING_TYPE = 0 + GROUPED = 474540862 + GROUP_MAINTENANCE_TYPE_UNSPECIFIED = 447183678 + INDEPENDENT = 127011674 + + maintenance_ongoing_count: int = proto.Field( + proto.INT32, + number=219781919, + optional=True, + ) + maintenance_pending_count: int = proto.Field( + proto.INT32, + number=158783547, + optional=True, + ) + scheduling_type: str = proto.Field( + proto.STRING, + number=199835397, + optional=True, + ) + upcoming_group_maintenance: "UpcomingMaintenance" = proto.Field( + proto.MESSAGE, + number=393438448, + optional=True, + message="UpcomingMaintenance", + ) + + class GuestAttributes(proto.Message): r"""A guest attributes entry. @@ -35612,9 +35844,10 @@ class GuestOsFeature(proto.Message): following values: - VIRTIO_SCSI_MULTIQUEUE - WINDOWS - MULTI_IP_SUBNET - UEFI_COMPATIBLE - GVNIC - SEV_CAPABLE - SUSPEND_RESUME_COMPATIBLE - SEV_LIVE_MIGRATABLE_V2 - - SEV_SNP_CAPABLE - TDX_CAPABLE - IDPF For more information, - see Enabling guest operating system features. Check the Type - enum for the list of possible values. + SEV_SNP_CAPABLE - TDX_CAPABLE - IDPF - SNP_SVSM_CAPABLE For + more information, see Enabling guest operating system + features. Check the Type enum for the list of possible + values. This field is a member of `oneof`_ ``_type``. """ @@ -35624,8 +35857,9 @@ class Type(proto.Enum): separate values. Set to one or more of the following values: - VIRTIO_SCSI_MULTIQUEUE - WINDOWS - MULTI_IP_SUBNET - UEFI_COMPATIBLE - GVNIC - SEV_CAPABLE - SUSPEND_RESUME_COMPATIBLE - - SEV_LIVE_MIGRATABLE_V2 - SEV_SNP_CAPABLE - TDX_CAPABLE - IDPF For - more information, see Enabling guest operating system features. + SEV_LIVE_MIGRATABLE_V2 - SEV_SNP_CAPABLE - TDX_CAPABLE - IDPF - + SNP_SVSM_CAPABLE For more information, see Enabling guest operating + system features. Values: UNDEFINED_TYPE (0): @@ -48333,9 +48567,10 @@ class InstancesReportHostAsFaultyRequest(proto.Message): Attributes: disruption_schedule (str): - The disruption schedule for the VM. Default - to IMMEDIATE. Check the DisruptionSchedule enum - for the list of possible values. + The disruption schedule for the VM. Required + field, only allows IMMEDIATE. Check the + DisruptionSchedule enum for the list of possible + values. This field is a member of `oneof`_ ``_disruption_schedule``. fault_reasons (MutableSequence[google.cloud.compute_v1.types.InstancesReportHostAsFaultyRequestFaultReason]): @@ -48343,7 +48578,8 @@ class InstancesReportHostAsFaultyRequest(proto.Message): """ class DisruptionSchedule(proto.Enum): - r"""The disruption schedule for the VM. Default to IMMEDIATE. + r"""The disruption schedule for the VM. Required field, only + allows IMMEDIATE. Values: UNDEFINED_DISRUPTION_SCHEDULE (0): @@ -51421,8 +51657,9 @@ class InterconnectLocation(proto.Message): [Output only] List of link types available at this InterconnectLocation, which can take one of the following values: - LINK_TYPE_ETHERNET_10G_LR - - LINK_TYPE_ETHERNET_100G_LR Check the AvailableLinkTypes enum - for the list of possible values. + LINK_TYPE_ETHERNET_100G_LR - LINK_TYPE_ETHERNET_400G_LR4 + Check the AvailableLinkTypes enum for the list of possible + values. city (str): [Output Only] Metropolitan area designator that indicates which city an interconnect is located. For example: @@ -64726,8 +64963,8 @@ class ListRegionsRequest(proto.Message): ) -class ListReservationsRequest(proto.Message): - r"""A request message for Reservations.List. See the method +class ListReservationBlocksRequest(proto.Message): + r"""A request message for ReservationBlocks.List. See the method description for details. @@ -64808,6 +65045,9 @@ class ListReservationsRequest(proto.Message): This field is a member of `oneof`_ ``_page_token``. project (str): Project ID for this request. + reservation (str): + The name of the reservation. Name should + conform to RFC1035 or be a resource ID. return_partial_success (bool): Opt-in for partial success behavior which provides partial results in case of failure. The @@ -64819,7 +65059,8 @@ class ListReservationsRequest(proto.Message): This field is a member of `oneof`_ ``_return_partial_success``. zone (str): - Name of the zone for this request. + Name of the zone for this request. Zone name + should conform to RFC1035. """ filter: str = proto.Field( @@ -64846,6 +65087,10 @@ class ListReservationsRequest(proto.Message): proto.STRING, number=227560217, ) + reservation: str = proto.Field( + proto.STRING, + number=47530956, + ) return_partial_success: bool = proto.Field( proto.BOOL, number=517198390, @@ -64857,8 +65102,8 @@ class ListReservationsRequest(proto.Message): ) -class ListResourcePoliciesRequest(proto.Message): - r"""A request message for ResourcePolicies.List. See the method +class ListReservationsRequest(proto.Message): + r"""A request message for Reservations.List. See the method description for details. @@ -64939,8 +65184,6 @@ class ListResourcePoliciesRequest(proto.Message): This field is a member of `oneof`_ ``_page_token``. project (str): Project ID for this request. - region (str): - Name of the region for this request. return_partial_success (bool): Opt-in for partial success behavior which provides partial results in case of failure. The @@ -64951,6 +65194,8 @@ class ListResourcePoliciesRequest(proto.Message): resources, with an error code. This field is a member of `oneof`_ ``_return_partial_success``. + zone (str): + Name of the zone for this request. """ filter: str = proto.Field( @@ -64977,20 +65222,20 @@ class ListResourcePoliciesRequest(proto.Message): proto.STRING, number=227560217, ) - region: str = proto.Field( - proto.STRING, - number=138946292, - ) return_partial_success: bool = proto.Field( proto.BOOL, number=517198390, optional=True, ) + zone: str = proto.Field( + proto.STRING, + number=3744684, + ) -class ListRoutePoliciesRoutersRequest(proto.Message): - r"""A request message for Routers.ListRoutePolicies. See the - method description for details. +class ListResourcePoliciesRequest(proto.Message): + r"""A request message for ResourcePolicies.List. See the method + description for details. .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields @@ -65082,9 +65327,6 @@ class ListRoutePoliciesRoutersRequest(proto.Message): resources, with an error code. This field is a member of `oneof`_ ``_return_partial_success``. - router (str): - Name or id of the resource for this request. - Name should conform to RFC1035. """ filter: str = proto.Field( @@ -65120,15 +65362,11 @@ class ListRoutePoliciesRoutersRequest(proto.Message): number=517198390, optional=True, ) - router: str = proto.Field( - proto.STRING, - number=148608841, - ) -class ListRoutersRequest(proto.Message): - r"""A request message for Routers.List. See the method - description for details. +class ListRoutePoliciesRoutersRequest(proto.Message): + r"""A request message for Routers.ListRoutePolicies. See the + method description for details. .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields @@ -65220,6 +65458,9 @@ class ListRoutersRequest(proto.Message): resources, with an error code. This field is a member of `oneof`_ ``_return_partial_success``. + router (str): + Name or id of the resource for this request. + Name should conform to RFC1035. """ filter: str = proto.Field( @@ -65255,11 +65496,15 @@ class ListRoutersRequest(proto.Message): number=517198390, optional=True, ) + router: str = proto.Field( + proto.STRING, + number=148608841, + ) -class ListRoutesRequest(proto.Message): - r"""A request message for Routes.List. See the method description - for details. +class ListRoutersRequest(proto.Message): + r"""A request message for Routers.List. See the method + description for details. .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields @@ -65339,6 +65584,8 @@ class ListRoutesRequest(proto.Message): This field is a member of `oneof`_ ``_page_token``. project (str): Project ID for this request. + region (str): + Name of the region for this request. return_partial_success (bool): Opt-in for partial success behavior which provides partial results in case of failure. The @@ -65375,6 +65622,10 @@ class ListRoutesRequest(proto.Message): proto.STRING, number=227560217, ) + region: str = proto.Field( + proto.STRING, + number=138946292, + ) return_partial_success: bool = proto.Field( proto.BOOL, number=517198390, @@ -65382,9 +65633,9 @@ class ListRoutesRequest(proto.Message): ) -class ListSecurityPoliciesRequest(proto.Message): - r"""A request message for SecurityPolicies.List. See the method - description for details. +class ListRoutesRequest(proto.Message): + r"""A request message for Routes.List. See the method description + for details. .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields @@ -65507,8 +65758,8 @@ class ListSecurityPoliciesRequest(proto.Message): ) -class ListServiceAttachmentsRequest(proto.Message): - r"""A request message for ServiceAttachments.List. See the method +class ListSecurityPoliciesRequest(proto.Message): + r"""A request message for SecurityPolicies.List. See the method description for details. @@ -65589,8 +65840,6 @@ class ListServiceAttachmentsRequest(proto.Message): This field is a member of `oneof`_ ``_page_token``. project (str): Project ID for this request. - region (str): - Name of the region of this request. return_partial_success (bool): Opt-in for partial success behavior which provides partial results in case of failure. The @@ -65627,10 +65876,6 @@ class ListServiceAttachmentsRequest(proto.Message): proto.STRING, number=227560217, ) - region: str = proto.Field( - proto.STRING, - number=138946292, - ) return_partial_success: bool = proto.Field( proto.BOOL, number=517198390, @@ -65638,8 +65883,8 @@ class ListServiceAttachmentsRequest(proto.Message): ) -class ListSnapshotsRequest(proto.Message): - r"""A request message for Snapshots.List. See the method +class ListServiceAttachmentsRequest(proto.Message): + r"""A request message for ServiceAttachments.List. See the method description for details. @@ -65720,6 +65965,8 @@ class ListSnapshotsRequest(proto.Message): This field is a member of `oneof`_ ``_page_token``. project (str): Project ID for this request. + region (str): + Name of the region of this request. return_partial_success (bool): Opt-in for partial success behavior which provides partial results in case of failure. The @@ -65756,6 +66003,10 @@ class ListSnapshotsRequest(proto.Message): proto.STRING, number=227560217, ) + region: str = proto.Field( + proto.STRING, + number=138946292, + ) return_partial_success: bool = proto.Field( proto.BOOL, number=517198390, @@ -65763,8 +66014,8 @@ class ListSnapshotsRequest(proto.Message): ) -class ListSslCertificatesRequest(proto.Message): - r"""A request message for SslCertificates.List. See the method +class ListSnapshotsRequest(proto.Message): + r"""A request message for Snapshots.List. See the method description for details. @@ -65888,8 +66139,8 @@ class ListSslCertificatesRequest(proto.Message): ) -class ListSslPoliciesRequest(proto.Message): - r"""A request message for SslPolicies.List. See the method +class ListSslCertificatesRequest(proto.Message): + r"""A request message for SslCertificates.List. See the method description for details. @@ -66013,8 +66264,8 @@ class ListSslPoliciesRequest(proto.Message): ) -class ListStoragePoolTypesRequest(proto.Message): - r"""A request message for StoragePoolTypes.List. See the method +class ListSslPoliciesRequest(proto.Message): + r"""A request message for SslPolicies.List. See the method description for details. @@ -66105,8 +66356,6 @@ class ListStoragePoolTypesRequest(proto.Message): resources, with an error code. This field is a member of `oneof`_ ``_return_partial_success``. - zone (str): - The name of the zone for this request. """ filter: str = proto.Field( @@ -66138,14 +66387,10 @@ class ListStoragePoolTypesRequest(proto.Message): number=517198390, optional=True, ) - zone: str = proto.Field( - proto.STRING, - number=3744684, - ) -class ListStoragePoolsRequest(proto.Message): - r"""A request message for StoragePools.List. See the method +class ListStoragePoolTypesRequest(proto.Message): + r"""A request message for StoragePoolTypes.List. See the method description for details. @@ -66275,8 +66520,8 @@ class ListStoragePoolsRequest(proto.Message): ) -class ListSubnetworksRequest(proto.Message): - r"""A request message for Subnetworks.List. See the method +class ListStoragePoolsRequest(proto.Message): + r"""A request message for StoragePools.List. See the method description for details. @@ -66357,8 +66602,6 @@ class ListSubnetworksRequest(proto.Message): This field is a member of `oneof`_ ``_page_token``. project (str): Project ID for this request. - region (str): - Name of the region scoping this request. return_partial_success (bool): Opt-in for partial success behavior which provides partial results in case of failure. The @@ -66369,6 +66612,8 @@ class ListSubnetworksRequest(proto.Message): resources, with an error code. This field is a member of `oneof`_ ``_return_partial_success``. + zone (str): + The name of the zone for this request. """ filter: str = proto.Field( @@ -66395,19 +66640,19 @@ class ListSubnetworksRequest(proto.Message): proto.STRING, number=227560217, ) - region: str = proto.Field( - proto.STRING, - number=138946292, - ) return_partial_success: bool = proto.Field( proto.BOOL, number=517198390, optional=True, ) + zone: str = proto.Field( + proto.STRING, + number=3744684, + ) -class ListTargetGrpcProxiesRequest(proto.Message): - r"""A request message for TargetGrpcProxies.List. See the method +class ListSubnetworksRequest(proto.Message): + r"""A request message for Subnetworks.List. See the method description for details. @@ -66488,6 +66733,8 @@ class ListTargetGrpcProxiesRequest(proto.Message): This field is a member of `oneof`_ ``_page_token``. project (str): Project ID for this request. + region (str): + Name of the region scoping this request. return_partial_success (bool): Opt-in for partial success behavior which provides partial results in case of failure. The @@ -66524,6 +66771,10 @@ class ListTargetGrpcProxiesRequest(proto.Message): proto.STRING, number=227560217, ) + region: str = proto.Field( + proto.STRING, + number=138946292, + ) return_partial_success: bool = proto.Field( proto.BOOL, number=517198390, @@ -66531,8 +66782,8 @@ class ListTargetGrpcProxiesRequest(proto.Message): ) -class ListTargetHttpProxiesRequest(proto.Message): - r"""A request message for TargetHttpProxies.List. See the method +class ListTargetGrpcProxiesRequest(proto.Message): + r"""A request message for TargetGrpcProxies.List. See the method description for details. @@ -66656,8 +66907,8 @@ class ListTargetHttpProxiesRequest(proto.Message): ) -class ListTargetHttpsProxiesRequest(proto.Message): - r"""A request message for TargetHttpsProxies.List. See the method +class ListTargetHttpProxiesRequest(proto.Message): + r"""A request message for TargetHttpProxies.List. See the method description for details. @@ -66781,8 +67032,8 @@ class ListTargetHttpsProxiesRequest(proto.Message): ) -class ListTargetInstancesRequest(proto.Message): - r"""A request message for TargetInstances.List. See the method +class ListTargetHttpsProxiesRequest(proto.Message): + r"""A request message for TargetHttpsProxies.List. See the method description for details. @@ -66873,8 +67124,6 @@ class ListTargetInstancesRequest(proto.Message): resources, with an error code. This field is a member of `oneof`_ ``_return_partial_success``. - zone (str): - Name of the zone scoping this request. """ filter: str = proto.Field( @@ -66906,14 +67155,10 @@ class ListTargetInstancesRequest(proto.Message): number=517198390, optional=True, ) - zone: str = proto.Field( - proto.STRING, - number=3744684, - ) -class ListTargetPoolsRequest(proto.Message): - r"""A request message for TargetPools.List. See the method +class ListTargetInstancesRequest(proto.Message): + r"""A request message for TargetInstances.List. See the method description for details. @@ -66994,8 +67239,139 @@ class ListTargetPoolsRequest(proto.Message): This field is a member of `oneof`_ ``_page_token``. project (str): Project ID for this request. - region (str): - Name of the region scoping this request. + return_partial_success (bool): + Opt-in for partial success behavior which + provides partial results in case of failure. The + default value is false. For example, when + partial success behavior is enabled, + aggregatedList for a single zone scope either + returns all resources in the zone or no + resources, with an error code. + + This field is a member of `oneof`_ ``_return_partial_success``. + zone (str): + Name of the zone scoping this request. + """ + + filter: str = proto.Field( + proto.STRING, + number=336120696, + optional=True, + ) + max_results: int = proto.Field( + proto.UINT32, + number=54715419, + optional=True, + ) + order_by: str = proto.Field( + proto.STRING, + number=160562920, + optional=True, + ) + page_token: str = proto.Field( + proto.STRING, + number=19994697, + optional=True, + ) + project: str = proto.Field( + proto.STRING, + number=227560217, + ) + return_partial_success: bool = proto.Field( + proto.BOOL, + number=517198390, + optional=True, + ) + zone: str = proto.Field( + proto.STRING, + number=3744684, + ) + + +class ListTargetPoolsRequest(proto.Message): + r"""A request message for TargetPools.List. See the method + description for details. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + filter (str): + A filter expression that filters resources listed in the + response. Most Compute resources support two types of filter + expressions: expressions that support regular expressions + and expressions that follow API improvement proposal + AIP-160. These two types of filter expressions cannot be + mixed in one request. If you want to use AIP-160, your + expression must specify the field name, an operator, and the + value that you want to use for filtering. The value must be + a string, a number, or a boolean. The operator must be + either ``=``, ``!=``, ``>``, ``<``, ``<=``, ``>=`` or ``:``. + For example, if you are filtering Compute Engine instances, + you can exclude instances named ``example-instance`` by + specifying ``name != example-instance``. The ``:*`` + comparison can be used to test whether a key has been + defined. For example, to find all objects with ``owner`` + label use: ``labels.owner:*`` You can also filter nested + fields. For example, you could specify + ``scheduling.automaticRestart = false`` to include instances + only if they are not scheduled for automatic restarts. You + can use filtering on nested fields to filter based on + resource labels. To filter on multiple expressions, provide + each separate expression within parentheses. For example: + ``(scheduling.automaticRestart = true) (cpuPlatform = "Intel Skylake")`` + By default, each expression is an ``AND`` expression. + However, you can include ``AND`` and ``OR`` expressions + explicitly. For example: + ``(cpuPlatform = "Intel Skylake") OR (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = true)`` + If you want to use a regular expression, use the ``eq`` + (equal) or ``ne`` (not equal) operator against a single + un-parenthesized expression with or without quotes or + against multiple parenthesized expressions. Examples: + ``fieldname eq unquoted literal`` + ``fieldname eq 'single quoted literal'`` + ``fieldname eq "double quoted literal"`` + ``(fieldname1 eq literal) (fieldname2 ne "literal")`` The + literal value is interpreted as a regular expression using + Google RE2 library syntax. The literal value must match the + entire field. For example, to filter for instances that do + not end with name "instance", you would use + ``name ne .*instance``. You cannot combine constraints on + multiple fields using regular expressions. + + This field is a member of `oneof`_ ``_filter``. + max_results (int): + The maximum number of results per page that should be + returned. If the number of available results is larger than + ``maxResults``, Compute Engine returns a ``nextPageToken`` + that can be used to get the next page of results in + subsequent list requests. Acceptable values are ``0`` to + ``500``, inclusive. (Default: ``500``) + + This field is a member of `oneof`_ ``_max_results``. + order_by (str): + Sorts list results by a certain order. By default, results + are returned in alphanumerical order based on the resource + name. You can also sort results in descending order based on + the creation timestamp using + ``orderBy="creationTimestamp desc"``. This sorts results + based on the ``creationTimestamp`` field in reverse + chronological order (newest result first). Use this to sort + resources like operations so that the newest operation is + returned first. Currently, only sorting by ``name`` or + ``creationTimestamp desc`` is supported. + + This field is a member of `oneof`_ ``_order_by``. + page_token (str): + Specifies a page token to use. Set ``pageToken`` to the + ``nextPageToken`` returned by a previous list request to get + the next page of results. + + This field is a member of `oneof`_ ``_page_token``. + project (str): + Project ID for this request. + region (str): + Name of the region scoping this request. return_partial_success (bool): Opt-in for partial success behavior which provides partial results in case of failure. The @@ -68843,6 +69219,22 @@ class MachineImage(proto.Message): compute#machineImage for machine image. This field is a member of `oneof`_ ``_kind``. + label_fingerprint (str): + A fingerprint for the labels being applied to + this machine image, which is essentially a hash + of the labels set used for optimistic locking. + The fingerprint is initially generated by + Compute Engine and changes after every request + to modify or update labels. You must always + provide an up-to-date fingerprint hash in order + to update or change labels. To see the latest + fingerprint, make get() request to the machine + image. + + This field is a member of `oneof`_ ``_label_fingerprint``. + labels (MutableMapping[str, str]): + Labels to apply to this machine image. These + can be later modified by the setLabels method. machine_image_encryption_key (google.cloud.compute_v1.types.CustomerEncryptionKey): Encrypts the machine image using a customer-supplied encryption key. After you @@ -68984,6 +69376,16 @@ class Status(proto.Enum): number=3292052, optional=True, ) + label_fingerprint: str = proto.Field( + proto.STRING, + number=178124825, + optional=True, + ) + labels: MutableMapping[str, str] = proto.MapField( + proto.STRING, + proto.STRING, + number=500195327, + ) machine_image_encryption_key: "CustomerEncryptionKey" = proto.Field( proto.MESSAGE, number=528089087, @@ -73031,7 +73433,8 @@ class NetworkPeering(proto.Message): This field is a member of `oneof`_ ``_network``. peer_mtu (int): - Maximum Transmission Unit in bytes. + [Output Only] Maximum Transmission Unit in bytes of the peer + network. This field is a member of `oneof`_ ``_peer_mtu``. stack_type (str): @@ -73387,6 +73790,12 @@ class NetworkProfileNetworkFeatures(proto.Message): list of possible values. This field is a member of `oneof`_ ``_allow_cloud_router``. + allow_default_nic_attachment (str): + Specifies whether default NIC attachment is + allowed. Check the AllowDefaultNicAttachment + enum for the list of possible values. + + This field is a member of `oneof`_ ``_allow_default_nic_attachment``. allow_external_ip_access (str): Specifies whether VMs are allowed to have external IP access on network interfaces @@ -73401,6 +73810,12 @@ class NetworkProfileNetworkFeatures(proto.Message): the list of possible values. This field is a member of `oneof`_ ``_allow_interconnect``. + allow_ip_forwarding (str): + Specifies whether IP forwarding is allowed. + Check the AllowIpForwarding enum for the list of + possible values. + + This field is a member of `oneof`_ ``_allow_ip_forwarding``. allow_load_balancing (str): Specifies whether cloud load balancing is allowed. Check the AllowLoadBalancing enum for @@ -73414,6 +73829,18 @@ class NetworkProfileNetworkFeatures(proto.Message): possible values. This field is a member of `oneof`_ ``_allow_multi_nic_in_same_network``. + allow_ncc (str): + Specifies whether NCC is allowed. + Check the AllowNcc enum for the list of possible + values. + + This field is a member of `oneof`_ ``_allow_ncc``. + allow_network_migration (str): + Specifies whether VM network migration is + allowed. Check the AllowNetworkMigration enum + for the list of possible values. + + This field is a member of `oneof`_ ``_allow_network_migration``. allow_packet_mirroring (str): Specifies whether Packet Mirroring 1.0 is supported. Check the AllowPacketMirroring enum @@ -73476,6 +73903,14 @@ class NetworkProfileNetworkFeatures(proto.Message): Specifies which subnetwork stack types are supported. Check the SubnetStackTypes enum for the list of possible values. + subnetwork_purposes (MutableSequence[str]): + Specifies which subnetwork purposes are + supported. Check the SubnetworkPurposes enum for + the list of possible values. + subnetwork_stack_types (MutableSequence[str]): + Specifies which subnetwork stack types are + supported. Check the SubnetworkStackTypes enum + for the list of possible values. unicast (str): Specifies which type of unicast is supported. Check the Unicast enum for the list of possible @@ -73485,7 +73920,8 @@ class NetworkProfileNetworkFeatures(proto.Message): """ class AddressPurposes(proto.Enum): - r""" + r"""Additional supported values which may be not listed in the enum + directly due to technical reasons: PRIVATE_SERVICE_CONNECT Values: UNDEFINED_ADDRESS_PURPOSES (0): @@ -73511,10 +73947,7 @@ class AddressPurposes(proto.Enum): External IP automatically reserved for Cloud NAT. PRIVATE_SERVICE_CONNECT (48134724): - A private network IP address that can be used - to configure Private Service Connect. This - purpose can be specified only for GLOBAL - addresses of Type INTERNAL + No description available. SERVERLESS (270492508): A regional internal IP address range reserved for Serverless. @@ -73617,6 +74050,22 @@ class AllowCloudRouter(proto.Enum): CLOUD_ROUTER_ALLOWED = 365388284 CLOUD_ROUTER_BLOCKED = 181551680 + class AllowDefaultNicAttachment(proto.Enum): + r"""Specifies whether default NIC attachment is allowed. + + Values: + UNDEFINED_ALLOW_DEFAULT_NIC_ATTACHMENT (0): + A value indicating that the enum field is not + set. + DEFAULT_NIC_ATTACHMENT_ALLOWED (11570689): + No description available. + DEFAULT_NIC_ATTACHMENT_BLOCKED (364604997): + No description available. + """ + UNDEFINED_ALLOW_DEFAULT_NIC_ATTACHMENT = 0 + DEFAULT_NIC_ATTACHMENT_ALLOWED = 11570689 + DEFAULT_NIC_ATTACHMENT_BLOCKED = 364604997 + class AllowExternalIpAccess(proto.Enum): r"""Specifies whether VMs are allowed to have external IP access on network interfaces connected to this VPC. @@ -73650,6 +74099,22 @@ class AllowInterconnect(proto.Enum): INTERCONNECT_ALLOWED = 162845399 INTERCONNECT_BLOCKED = 515879707 + class AllowIpForwarding(proto.Enum): + r"""Specifies whether IP forwarding is allowed. + + Values: + UNDEFINED_ALLOW_IP_FORWARDING (0): + A value indicating that the enum field is not + set. + IP_FORWARDING_ALLOWED (152595550): + No description available. + IP_FORWARDING_BLOCKED (505629858): + No description available. + """ + UNDEFINED_ALLOW_IP_FORWARDING = 0 + IP_FORWARDING_ALLOWED = 152595550 + IP_FORWARDING_BLOCKED = 505629858 + class AllowLoadBalancing(proto.Enum): r"""Specifies whether cloud load balancing is allowed. @@ -73682,6 +74147,38 @@ class AllowMultiNicInSameNetwork(proto.Enum): MULTI_NIC_IN_SAME_NETWORK_ALLOWED = 457555419 MULTI_NIC_IN_SAME_NETWORK_BLOCKED = 273718815 + class AllowNcc(proto.Enum): + r"""Specifies whether NCC is allowed. + + Values: + UNDEFINED_ALLOW_NCC (0): + A value indicating that the enum field is not + set. + NCC_ALLOWED (467227511): + No description available. + NCC_BLOCKED (283390907): + No description available. + """ + UNDEFINED_ALLOW_NCC = 0 + NCC_ALLOWED = 467227511 + NCC_BLOCKED = 283390907 + + class AllowNetworkMigration(proto.Enum): + r"""Specifies whether VM network migration is allowed. + + Values: + UNDEFINED_ALLOW_NETWORK_MIGRATION (0): + A value indicating that the enum field is not + set. + NETWORK_MIGRATION_ALLOWED (14389766): + No description available. + NETWORK_MIGRATION_BLOCKED (367424074): + No description available. + """ + UNDEFINED_ALLOW_NETWORK_MIGRATION = 0 + NETWORK_MIGRATION_ALLOWED = 14389766 + NETWORK_MIGRATION_BLOCKED = 367424074 + class AllowPacketMirroring(proto.Enum): r"""Specifies whether Packet Mirroring 1.0 is supported. @@ -73873,6 +74370,69 @@ class SubnetStackTypes(proto.Enum): SUBNET_STACK_TYPE_IPV4_ONLY = 41631034 SUBNET_STACK_TYPE_IPV6_ONLY = 98889336 + class SubnetworkPurposes(proto.Enum): + r"""Additional supported values which may be not listed in the enum + directly due to technical reasons: PRIVATE_SERVICE_CONNECT + + Values: + UNDEFINED_SUBNETWORK_PURPOSES (0): + A value indicating that the enum field is not + set. + GLOBAL_MANAGED_PROXY (236463602): + Subnet reserved for Global Envoy-based Load + Balancing. + INTERNAL_HTTPS_LOAD_BALANCER (248748889): + Subnet reserved for Internal HTTP(S) Load Balancing. This is + a legacy purpose, please use REGIONAL_MANAGED_PROXY instead. + PEER_MIGRATION (491902225): + Subnetwork will be used for Migration from + one peered VPC to another. (a transient state of + subnetwork while migrating resources from one + project to another). + PRIVATE (403485027): + Regular user created or automatically created + subnet. + PRIVATE_NAT (367764517): + Subnetwork used as source range for Private + NAT Gateways. + PRIVATE_RFC_1918 (254902107): + Regular user created or automatically created + subnet. + REGIONAL_MANAGED_PROXY (153049966): + Subnetwork used for Regional Envoy-based Load + Balancing. + """ + UNDEFINED_SUBNETWORK_PURPOSES = 0 + GLOBAL_MANAGED_PROXY = 236463602 + INTERNAL_HTTPS_LOAD_BALANCER = 248748889 + PEER_MIGRATION = 491902225 + PRIVATE = 403485027 + PRIVATE_NAT = 367764517 + PRIVATE_RFC_1918 = 254902107 + REGIONAL_MANAGED_PROXY = 153049966 + + class SubnetworkStackTypes(proto.Enum): + r""" + + Values: + UNDEFINED_SUBNETWORK_STACK_TYPES (0): + A value indicating that the enum field is not + set. + IPV4_IPV6 (22197249): + New VMs in this subnet can have both IPv4 and + IPv6 addresses. + IPV4_ONLY (22373798): + New VMs in this subnet will only be assigned + IPv4 addresses. + IPV6_ONLY (79632100): + New VMs in this subnet will only be assigned + IPv6 addresses. + """ + UNDEFINED_SUBNETWORK_STACK_TYPES = 0 + IPV4_IPV6 = 22197249 + IPV4_ONLY = 22373798 + IPV6_ONLY = 79632100 + class Unicast(proto.Enum): r"""Specifies which type of unicast is supported. @@ -73918,6 +74478,11 @@ class Unicast(proto.Enum): number=451110345, optional=True, ) + allow_default_nic_attachment: str = proto.Field( + proto.STRING, + number=53917486, + optional=True, + ) allow_external_ip_access: str = proto.Field( proto.STRING, number=131538110, @@ -73928,6 +74493,11 @@ class Unicast(proto.Enum): number=280512964, optional=True, ) + allow_ip_forwarding: str = proto.Field( + proto.STRING, + number=500838047, + optional=True, + ) allow_load_balancing: str = proto.Field( proto.STRING, number=223366198, @@ -73938,6 +74508,16 @@ class Unicast(proto.Enum): number=88251004, optional=True, ) + allow_ncc: str = proto.Field( + proto.STRING, + number=372354904, + optional=True, + ) + allow_network_migration: str = proto.Field( + proto.STRING, + number=239588231, + optional=True, + ) allow_packet_mirroring: str = proto.Field( proto.STRING, number=512227074, @@ -73990,6 +74570,14 @@ class Unicast(proto.Enum): proto.STRING, number=521008672, ) + subnetwork_purposes: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=528240710, + ) + subnetwork_stack_types: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=436827441, + ) unicast: str = proto.Field( proto.STRING, number=249841711, @@ -81437,6 +82025,137 @@ class PerformMaintenanceNodeGroupRequest(proto.Message): ) +class PerformMaintenanceReservationBlockRequest(proto.Message): + r"""A request message for ReservationBlocks.PerformMaintenance. + See the method description for details. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + project (str): + Project ID for this request. + request_id (str): + An optional request ID to identify requests. + Specify a unique request ID so that if you must + retry your request, the server will know to + ignore the request if it has already been + completed. For example, consider a situation + where you make an initial request and the + request times out. If you make the request again + with the same request ID, the server can check + if original operation with the same request ID + was received, and if so, will ignore the second + request. This prevents clients from accidentally + creating duplicate commitments. The request ID + must be a valid UUID with the exception that + zero UUID is not supported ( + 00000000-0000-0000-0000-000000000000). + + This field is a member of `oneof`_ ``_request_id``. + reservation (str): + The name of the reservation. Name should + conform to RFC1035 or be a resource ID. + reservation_block (str): + The name of the reservation block. Name + should conform to RFC1035 or be a resource ID. + reservations_blocks_perform_maintenance_request_resource (google.cloud.compute_v1.types.ReservationsBlocksPerformMaintenanceRequest): + The body resource for this request + zone (str): + Name of the zone for this request. Zone name + should conform to RFC1035. + """ + + project: str = proto.Field( + proto.STRING, + number=227560217, + ) + request_id: str = proto.Field( + proto.STRING, + number=37109963, + optional=True, + ) + reservation: str = proto.Field( + proto.STRING, + number=47530956, + ) + reservation_block: str = proto.Field( + proto.STRING, + number=532832858, + ) + reservations_blocks_perform_maintenance_request_resource: "ReservationsBlocksPerformMaintenanceRequest" = proto.Field( + proto.MESSAGE, + number=485823625, + message="ReservationsBlocksPerformMaintenanceRequest", + ) + zone: str = proto.Field( + proto.STRING, + number=3744684, + ) + + +class PerformMaintenanceReservationRequest(proto.Message): + r"""A request message for Reservations.PerformMaintenance. See + the method description for details. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + project (str): + Project ID for this request. + request_id (str): + An optional request ID to identify requests. + Specify a unique request ID so that if you must + retry your request, the server will know to + ignore the request if it has already been + completed. For example, consider a situation + where you make an initial request and the + request times out. If you make the request again + with the same request ID, the server can check + if original operation with the same request ID + was received, and if so, will ignore the second + request. This prevents clients from accidentally + creating duplicate commitments. The request ID + must be a valid UUID with the exception that + zero UUID is not supported ( + 00000000-0000-0000-0000-000000000000). + + This field is a member of `oneof`_ ``_request_id``. + reservation (str): + The name of the reservation. Name should + conform to RFC1035 or be a resource ID. + reservations_perform_maintenance_request_resource (google.cloud.compute_v1.types.ReservationsPerformMaintenanceRequest): + The body resource for this request + zone (str): + Name of the zone for this request. Zone name + should conform to RFC1035. + """ + + project: str = proto.Field( + proto.STRING, + number=227560217, + ) + request_id: str = proto.Field( + proto.STRING, + number=37109963, + optional=True, + ) + reservation: str = proto.Field( + proto.STRING, + number=47530956, + ) + reservations_perform_maintenance_request_resource: "ReservationsPerformMaintenanceRequest" = proto.Field( + proto.MESSAGE, + number=29702816, + message="ReservationsPerformMaintenanceRequest", + ) + zone: str = proto.Field( + proto.STRING, + number=3744684, + ) + + class Policy(proto.Message): r"""An Identity and Access Management (IAM) policy, which specifies access controls for Google Cloud resources. A ``Policy`` is a @@ -86948,6 +87667,12 @@ class Reservation(proto.Message): [Output Only] Creation timestamp in RFC3339 text format. This field is a member of `oneof`_ ``_creation_timestamp``. + deployment_type (str): + Specifies the deployment strategy for this + reservation. Check the DeploymentType enum for + the list of possible values. + + This field is a member of `oneof`_ ``_deployment_type``. description (str): An optional description of this resource. Provide this property when you create the @@ -86964,6 +87689,10 @@ class Reservation(proto.Message): compute#reservations for reservations. This field is a member of `oneof`_ ``_kind``. + linked_commitments (MutableSequence[str]): + [Output Only] Full or partial URL to parent commitments. + This field displays for reservations that are tied to + multiple commitments. name (str): The name of the resource, provided by the client when initially creating the resource. The resource name must be @@ -87038,6 +87767,23 @@ class Reservation(proto.Message): This field is a member of `oneof`_ ``_zone``. """ + class DeploymentType(proto.Enum): + r"""Specifies the deployment strategy for this reservation. + + Values: + UNDEFINED_DEPLOYMENT_TYPE (0): + A value indicating that the enum field is not + set. + DENSE (64932607): + The reserved capacity is made up of densely + deployed reservation blocks. + DEPLOYMENT_TYPE_UNSPECIFIED (234847180): + No description available. + """ + UNDEFINED_DEPLOYMENT_TYPE = 0 + DENSE = 64932607 + DEPLOYMENT_TYPE_UNSPECIFIED = 234847180 + class Status(proto.Enum): r"""[Output Only] The status of the reservation. - CREATING: Reservation resources are being allocated. - READY: Reservation resources have @@ -87084,6 +87830,11 @@ class Status(proto.Enum): number=30525366, optional=True, ) + deployment_type: str = proto.Field( + proto.STRING, + number=396722292, + optional=True, + ) description: str = proto.Field( proto.STRING, number=422937596, @@ -87099,6 +87850,10 @@ class Status(proto.Enum): number=3292052, optional=True, ) + linked_commitments: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=470957784, + ) name: str = proto.Field( proto.STRING, number=3373707, @@ -87314,6 +88069,286 @@ def raw_page(self): ) +class ReservationBlock(proto.Message): + r"""Represents a reservation block resource. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + count (int): + [Output Only] The number of resources that are allocated in + this reservation block. + + This field is a member of `oneof`_ ``_count``. + creation_timestamp (str): + [Output Only] Creation timestamp in RFC3339 text format. + + This field is a member of `oneof`_ ``_creation_timestamp``. + id (int): + [Output Only] The unique identifier for the resource. This + identifier is defined by the server. + + This field is a member of `oneof`_ ``_id``. + in_use_count (int): + [Output Only] The number of instances that are currently in + use on this reservation block. + + This field is a member of `oneof`_ ``_in_use_count``. + kind (str): + [Output Only] Type of the resource. Always + compute#reservationBlock for reservation blocks. + + This field is a member of `oneof`_ ``_kind``. + name (str): + [Output Only] The name of this reservation block generated + by Google Compute Engine. The name must be 1-63 characters + long, and comply with RFC1035 @pattern + `a-z `__? + + This field is a member of `oneof`_ ``_name``. + physical_topology (google.cloud.compute_v1.types.ReservationBlockPhysicalTopology): + [Output Only] The physical topology of the reservation + block. + + This field is a member of `oneof`_ ``_physical_topology``. + reservation_maintenance (google.cloud.compute_v1.types.GroupMaintenanceInfo): + [Output Only] Maintenance information for this reservation + block. + + This field is a member of `oneof`_ ``_reservation_maintenance``. + self_link (str): + [Output Only] Server-defined fully-qualified URL for this + resource. + + This field is a member of `oneof`_ ``_self_link``. + self_link_with_id (str): + [Output Only] Server-defined URL for this resource with the + resource id. + + This field is a member of `oneof`_ ``_self_link_with_id``. + status (str): + [Output Only] Status of the reservation block. Check the + Status enum for the list of possible values. + + This field is a member of `oneof`_ ``_status``. + zone (str): + [Output Only] Zone in which the reservation block resides. + + This field is a member of `oneof`_ ``_zone``. + """ + + class Status(proto.Enum): + r"""[Output Only] Status of the reservation block. + + Values: + UNDEFINED_STATUS (0): + A value indicating that the enum field is not + set. + CREATING (455564985): + Resources are being allocated for the + reservation block. + DELETING (528602024): + Reservation block is currently being deleted. + INVALID (530283991): + No description available. + READY (77848963): + Reservation block has allocated all its + resources. + """ + UNDEFINED_STATUS = 0 + CREATING = 455564985 + DELETING = 528602024 + INVALID = 530283991 + READY = 77848963 + + count: int = proto.Field( + proto.INT32, + number=94851343, + optional=True, + ) + creation_timestamp: str = proto.Field( + proto.STRING, + number=30525366, + optional=True, + ) + id: int = proto.Field( + proto.UINT64, + number=3355, + optional=True, + ) + in_use_count: int = proto.Field( + proto.INT32, + number=493458877, + optional=True, + ) + kind: str = proto.Field( + proto.STRING, + number=3292052, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=3373707, + optional=True, + ) + physical_topology: "ReservationBlockPhysicalTopology" = proto.Field( + proto.MESSAGE, + number=279778519, + optional=True, + message="ReservationBlockPhysicalTopology", + ) + reservation_maintenance: "GroupMaintenanceInfo" = proto.Field( + proto.MESSAGE, + number=340607776, + optional=True, + message="GroupMaintenanceInfo", + ) + self_link: str = proto.Field( + proto.STRING, + number=456214797, + optional=True, + ) + self_link_with_id: str = proto.Field( + proto.STRING, + number=44520962, + optional=True, + ) + status: str = proto.Field( + proto.STRING, + number=181260274, + optional=True, + ) + zone: str = proto.Field( + proto.STRING, + number=3744684, + optional=True, + ) + + +class ReservationBlockPhysicalTopology(proto.Message): + r""" + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + block (str): + The hash of the capacity block within the + cluster. + + This field is a member of `oneof`_ ``_block``. + cluster (str): + The cluster name of the reservation block. + + This field is a member of `oneof`_ ``_cluster``. + """ + + block: str = proto.Field( + proto.STRING, + number=93832333, + optional=True, + ) + cluster: str = proto.Field( + proto.STRING, + number=335221242, + optional=True, + ) + + +class ReservationBlocksGetResponse(proto.Message): + r""" + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource (google.cloud.compute_v1.types.ReservationBlock): + + This field is a member of `oneof`_ ``_resource``. + """ + + resource: "ReservationBlock" = proto.Field( + proto.MESSAGE, + number=195806222, + optional=True, + message="ReservationBlock", + ) + + +class ReservationBlocksListResponse(proto.Message): + r"""A list of reservation blocks under a single reservation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + id (str): + Unique identifier for the resource; defined + by the server. + + This field is a member of `oneof`_ ``_id``. + items (MutableSequence[google.cloud.compute_v1.types.ReservationBlock]): + A list of reservation block resources. + kind (str): + Type of the resource. Always + compute#reservationBlock for a list of + reservation blocks. + + This field is a member of `oneof`_ ``_kind``. + next_page_token (str): + This token allows you to get the next page of + results for list requests. If the number of + results is larger than maxResults, use the + nextPageToken as a value for the query parameter + pageToken in the next list request. Subsequent + list requests will have their own nextPageToken + to continue paging through the results. + + This field is a member of `oneof`_ ``_next_page_token``. + self_link (str): + Server-defined URL for this resource. + + This field is a member of `oneof`_ ``_self_link``. + warning (google.cloud.compute_v1.types.Warning): + Informational warning message. + + This field is a member of `oneof`_ ``_warning``. + """ + + @property + def raw_page(self): + return self + + id: str = proto.Field( + proto.STRING, + number=3355, + optional=True, + ) + items: MutableSequence["ReservationBlock"] = proto.RepeatedField( + proto.MESSAGE, + number=100526016, + message="ReservationBlock", + ) + kind: str = proto.Field( + proto.STRING, + number=3292052, + optional=True, + ) + next_page_token: str = proto.Field( + proto.STRING, + number=79797525, + optional=True, + ) + self_link: str = proto.Field( + proto.STRING, + number=456214797, + optional=True, + ) + warning: "Warning" = proto.Field( + proto.MESSAGE, + number=50704284, + optional=True, + message="Warning", + ) + + class ReservationList(proto.Message): r""" @@ -87388,6 +88423,110 @@ def raw_page(self): ) +class ReservationsBlocksPerformMaintenanceRequest(proto.Message): + r""" + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + maintenance_scope (str): + Specifies if all, running or unused hosts are + in scope for this request. Check the + MaintenanceScope enum for the list of possible + values. + + This field is a member of `oneof`_ ``_maintenance_scope``. + """ + + class MaintenanceScope(proto.Enum): + r"""Specifies if all, running or unused hosts are in scope for + this request. + + Values: + UNDEFINED_MAINTENANCE_SCOPE (0): + A value indicating that the enum field is not + set. + ALL (64897): + Trigger maintenance for all hosts belonging + to this reservation irrespective of whether VMs + are running on them or not. + MAINTENANCE_SCOPE_UNSPECIFIED (78827328): + Internal only + RUNNING_VMS (535770588): + Trigger maintenance only on the hosts + belonging to this reservation which have VMs + running on them. + UNUSED_CAPACITY (212724995): + Trigger maintenance only on the hosts + belonging to this reservation which do not have + any VMs running on them. This is not allowed for + Standard ExR + """ + UNDEFINED_MAINTENANCE_SCOPE = 0 + ALL = 64897 + MAINTENANCE_SCOPE_UNSPECIFIED = 78827328 + RUNNING_VMS = 535770588 + UNUSED_CAPACITY = 212724995 + + maintenance_scope: str = proto.Field( + proto.STRING, + number=140687912, + optional=True, + ) + + +class ReservationsPerformMaintenanceRequest(proto.Message): + r""" + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + maintenance_scope (str): + Specifies if all, running or unused hosts are + in scope for this request. Check the + MaintenanceScope enum for the list of possible + values. + + This field is a member of `oneof`_ ``_maintenance_scope``. + """ + + class MaintenanceScope(proto.Enum): + r"""Specifies if all, running or unused hosts are in scope for + this request. + + Values: + UNDEFINED_MAINTENANCE_SCOPE (0): + A value indicating that the enum field is not + set. + ALL (64897): + Trigger maintenance for all hosts belonging + to this reservation irrespective of whether VMs + are running on them or not. + MAINTENANCE_SCOPE_UNSPECIFIED (78827328): + Internal only + RUNNING_VMS (535770588): + Trigger maintenance only on the hosts + belonging to this reservation which have VMs + running on them. + UNUSED_CAPACITY (212724995): + Trigger maintenance only on the hosts + belonging to this reservation which do not have + any VMs running on them. This is not allowed for + Standard ExR + """ + UNDEFINED_MAINTENANCE_SCOPE = 0 + ALL = 64897 + MAINTENANCE_SCOPE_UNSPECIFIED = 78827328 + RUNNING_VMS = 535770588 + UNUSED_CAPACITY = 212724995 + + maintenance_scope: str = proto.Field( + proto.STRING, + number=140687912, + optional=True, + ) + + class ReservationsResizeRequest(proto.Message): r""" @@ -91088,6 +92227,11 @@ class RouterNat(proto.Message): RFC1035. This field is a member of `oneof`_ ``_name``. + nat64_subnetworks (MutableSequence[google.cloud.compute_v1.types.RouterNatSubnetworkToNat64]): + List of Subnetwork resources whose traffic should be + translated by NAT64 Gateway. It is used only when + LIST_OF_IPV6_SUBNETWORKS is selected for the + SubnetworkIpRangeToNat64Option above. nat_ip_allocate_option (str): Specify the NatIpAllocateOption, which can take one of the following values: - MANUAL_ONLY: Uses only Nat IP addresses @@ -91122,6 +92266,21 @@ class RouterNat(proto.Message): values. This field is a member of `oneof`_ ``_source_subnetwork_ip_ranges_to_nat``. + source_subnetwork_ip_ranges_to_nat64 (str): + Specify the Nat option for NAT64, which can take one of the + following values: - ALL_IPV6_SUBNETWORKS: All of the IP + ranges in every Subnetwork are allowed to Nat. - + LIST_OF_IPV6_SUBNETWORKS: A list of Subnetworks are allowed + to Nat (specified in the field nat64_subnetwork below) The + default is NAT64_OPTION_UNSPECIFIED. Note that if this field + contains NAT64_ALL_V6_SUBNETWORKS no other Router.Nat + section in this region can also enable NAT64 for any + Subnetworks in this network. Other Router.Nat sections can + still be present to enable NAT44 only. Check the + SourceSubnetworkIpRangesToNat64 enum for the list of + possible values. + + This field is a member of `oneof`_ ``_source_subnetwork_ip_ranges_to_nat64``. subnetworks (MutableSequence[google.cloud.compute_v1.types.RouterNatSubnetworkToNat]): A list of Subnetwork resources whose traffic should be translated by NAT Gateway. It is used only when @@ -91262,6 +92421,35 @@ class SourceSubnetworkIpRangesToNat(proto.Enum): ALL_SUBNETWORKS_ALL_PRIMARY_IP_RANGES = 185573819 LIST_OF_SUBNETWORKS = 517542270 + class SourceSubnetworkIpRangesToNat64(proto.Enum): + r"""Specify the Nat option for NAT64, which can take one of the + following values: - ALL_IPV6_SUBNETWORKS: All of the IP ranges in + every Subnetwork are allowed to Nat. - LIST_OF_IPV6_SUBNETWORKS: A + list of Subnetworks are allowed to Nat (specified in the field + nat64_subnetwork below) The default is NAT64_OPTION_UNSPECIFIED. + Note that if this field contains NAT64_ALL_V6_SUBNETWORKS no other + Router.Nat section in this region can also enable NAT64 for any + Subnetworks in this network. Other Router.Nat sections can still be + present to enable NAT44 only. + + Values: + UNDEFINED_SOURCE_SUBNETWORK_IP_RANGES_TO_NAT64 (0): + A value indicating that the enum field is not + set. + ALL_IPV6_SUBNETWORKS (341632747): + NAT64 is enabled for all the IPv6 subnet + ranges. In dual stack subnets, NAT64 will only + be enabled for IPv6-only VMs. + LIST_OF_IPV6_SUBNETWORKS (521079860): + NAT64 is enabled for a list of IPv6 subnet ranges. In dual + stack subnets, NAT64 will only be enabled for IPv6-only VMs. + If this option is used, the nat64_subnetworks field must be + specified. + """ + UNDEFINED_SOURCE_SUBNETWORK_IP_RANGES_TO_NAT64 = 0 + ALL_IPV6_SUBNETWORKS = 341632747 + LIST_OF_IPV6_SUBNETWORKS = 521079860 + class Type(proto.Enum): r"""Indicates whether this NAT is used for public or private IP translation. If unspecified, it defaults to PUBLIC. @@ -91329,6 +92517,13 @@ class Type(proto.Enum): number=3373707, optional=True, ) + nat64_subnetworks: MutableSequence[ + "RouterNatSubnetworkToNat64" + ] = proto.RepeatedField( + proto.MESSAGE, + number=63585701, + message="RouterNatSubnetworkToNat64", + ) nat_ip_allocate_option: str = proto.Field( proto.STRING, number=429726845, @@ -91348,6 +92543,11 @@ class Type(proto.Enum): number=252213211, optional=True, ) + source_subnetwork_ip_ranges_to_nat64: str = proto.Field( + proto.STRING, + number=248116185, + optional=True, + ) subnetworks: MutableSequence["RouterNatSubnetworkToNat"] = proto.RepeatedField( proto.MESSAGE, number=415853125, @@ -91609,6 +92809,26 @@ class SourceIpRangesToNat(proto.Enum): ) +class RouterNatSubnetworkToNat64(proto.Message): + r"""Specifies a subnetwork to enable NAT64. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + name (str): + URL for the subnetwork resource that will use + NAT64. + + This field is a member of `oneof`_ ``_name``. + """ + + name: str = proto.Field( + proto.STRING, + number=3373707, + optional=True, + ) + + class RouterStatus(proto.Message): r""" @@ -98123,64 +99343,272 @@ class SetLabelsForwardingRuleRequest(proto.Message): ) -class SetLabelsGlobalAddressRequest(proto.Message): - r"""A request message for GlobalAddresses.SetLabels. See the - method description for details. - - Attributes: - global_set_labels_request_resource (google.cloud.compute_v1.types.GlobalSetLabelsRequest): - The body resource for this request - project (str): - Project ID for this request. - resource (str): - Name or id of the resource for this request. - """ - - global_set_labels_request_resource: "GlobalSetLabelsRequest" = proto.Field( - proto.MESSAGE, - number=319917189, - message="GlobalSetLabelsRequest", - ) - project: str = proto.Field( - proto.STRING, - number=227560217, - ) - resource: str = proto.Field( - proto.STRING, - number=195806222, - ) - - -class SetLabelsGlobalForwardingRuleRequest(proto.Message): - r"""A request message for GlobalForwardingRules.SetLabels. See - the method description for details. - - Attributes: - global_set_labels_request_resource (google.cloud.compute_v1.types.GlobalSetLabelsRequest): - The body resource for this request - project (str): - Project ID for this request. - resource (str): - Name or id of the resource for this request. - """ - - global_set_labels_request_resource: "GlobalSetLabelsRequest" = proto.Field( - proto.MESSAGE, - number=319917189, - message="GlobalSetLabelsRequest", - ) - project: str = proto.Field( - proto.STRING, - number=227560217, - ) - resource: str = proto.Field( - proto.STRING, - number=195806222, - ) - - -class SetLabelsImageRequest(proto.Message): - r"""A request message for Images.SetLabels. See the method +class SetLabelsGlobalAddressRequest(proto.Message): + r"""A request message for GlobalAddresses.SetLabels. See the + method description for details. + + Attributes: + global_set_labels_request_resource (google.cloud.compute_v1.types.GlobalSetLabelsRequest): + The body resource for this request + project (str): + Project ID for this request. + resource (str): + Name or id of the resource for this request. + """ + + global_set_labels_request_resource: "GlobalSetLabelsRequest" = proto.Field( + proto.MESSAGE, + number=319917189, + message="GlobalSetLabelsRequest", + ) + project: str = proto.Field( + proto.STRING, + number=227560217, + ) + resource: str = proto.Field( + proto.STRING, + number=195806222, + ) + + +class SetLabelsGlobalForwardingRuleRequest(proto.Message): + r"""A request message for GlobalForwardingRules.SetLabels. See + the method description for details. + + Attributes: + global_set_labels_request_resource (google.cloud.compute_v1.types.GlobalSetLabelsRequest): + The body resource for this request + project (str): + Project ID for this request. + resource (str): + Name or id of the resource for this request. + """ + + global_set_labels_request_resource: "GlobalSetLabelsRequest" = proto.Field( + proto.MESSAGE, + number=319917189, + message="GlobalSetLabelsRequest", + ) + project: str = proto.Field( + proto.STRING, + number=227560217, + ) + resource: str = proto.Field( + proto.STRING, + number=195806222, + ) + + +class SetLabelsImageRequest(proto.Message): + r"""A request message for Images.SetLabels. See the method + description for details. + + Attributes: + global_set_labels_request_resource (google.cloud.compute_v1.types.GlobalSetLabelsRequest): + The body resource for this request + project (str): + Project ID for this request. + resource (str): + Name or id of the resource for this request. + """ + + global_set_labels_request_resource: "GlobalSetLabelsRequest" = proto.Field( + proto.MESSAGE, + number=319917189, + message="GlobalSetLabelsRequest", + ) + project: str = proto.Field( + proto.STRING, + number=227560217, + ) + resource: str = proto.Field( + proto.STRING, + number=195806222, + ) + + +class SetLabelsInstanceRequest(proto.Message): + r"""A request message for Instances.SetLabels. See the method + description for details. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + instance (str): + Name of the instance scoping this request. + instances_set_labels_request_resource (google.cloud.compute_v1.types.InstancesSetLabelsRequest): + The body resource for this request + project (str): + Project ID for this request. + request_id (str): + An optional request ID to identify requests. + Specify a unique request ID so that if you must + retry your request, the server will know to + ignore the request if it has already been + completed. For example, consider a situation + where you make an initial request and the + request times out. If you make the request again + with the same request ID, the server can check + if original operation with the same request ID + was received, and if so, will ignore the second + request. This prevents clients from accidentally + creating duplicate commitments. The request ID + must be a valid UUID with the exception that + zero UUID is not supported ( + 00000000-0000-0000-0000-000000000000). + + This field is a member of `oneof`_ ``_request_id``. + zone (str): + The name of the zone for this request. + """ + + instance: str = proto.Field( + proto.STRING, + number=18257045, + ) + instances_set_labels_request_resource: "InstancesSetLabelsRequest" = proto.Field( + proto.MESSAGE, + number=207749344, + message="InstancesSetLabelsRequest", + ) + project: str = proto.Field( + proto.STRING, + number=227560217, + ) + request_id: str = proto.Field( + proto.STRING, + number=37109963, + optional=True, + ) + zone: str = proto.Field( + proto.STRING, + number=3744684, + ) + + +class SetLabelsInstantSnapshotRequest(proto.Message): + r"""A request message for InstantSnapshots.SetLabels. See the + method description for details. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + project (str): + Project ID for this request. + request_id (str): + An optional request ID to identify requests. + Specify a unique request ID so that if you must + retry your request, the server will know to + ignore the request if it has already been + completed. For example, consider a situation + where you make an initial request and the + request times out. If you make the request again + with the same request ID, the server can check + if original operation with the same request ID + was received, and if so, will ignore the second + request. This prevents clients from accidentally + creating duplicate commitments. The request ID + must be a valid UUID with the exception that + zero UUID is not supported ( + 00000000-0000-0000-0000-000000000000). + + This field is a member of `oneof`_ ``_request_id``. + resource (str): + Name or id of the resource for this request. + zone (str): + The name of the zone for this request. + zone_set_labels_request_resource (google.cloud.compute_v1.types.ZoneSetLabelsRequest): + The body resource for this request + """ + + project: str = proto.Field( + proto.STRING, + number=227560217, + ) + request_id: str = proto.Field( + proto.STRING, + number=37109963, + optional=True, + ) + resource: str = proto.Field( + proto.STRING, + number=195806222, + ) + zone: str = proto.Field( + proto.STRING, + number=3744684, + ) + zone_set_labels_request_resource: "ZoneSetLabelsRequest" = proto.Field( + proto.MESSAGE, + number=364950798, + message="ZoneSetLabelsRequest", + ) + + +class SetLabelsInterconnectAttachmentRequest(proto.Message): + r"""A request message for InterconnectAttachments.SetLabels. See + the method description for details. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + project (str): + Project ID for this request. + region (str): + The region for this request. + region_set_labels_request_resource (google.cloud.compute_v1.types.RegionSetLabelsRequest): + The body resource for this request + request_id (str): + An optional request ID to identify requests. + Specify a unique request ID so that if you must + retry your request, the server will know to + ignore the request if it has already been + completed. For example, consider a situation + where you make an initial request and the + request times out. If you make the request again + with the same request ID, the server can check + if original operation with the same request ID + was received, and if so, will ignore the second + request. This prevents clients from accidentally + creating duplicate commitments. The request ID + must be a valid UUID with the exception that + zero UUID is not supported ( + 00000000-0000-0000-0000-000000000000). + + This field is a member of `oneof`_ ``_request_id``. + resource (str): + Name or id of the resource for this request. + """ + + project: str = proto.Field( + proto.STRING, + number=227560217, + ) + region: str = proto.Field( + proto.STRING, + number=138946292, + ) + region_set_labels_request_resource: "RegionSetLabelsRequest" = proto.Field( + proto.MESSAGE, + number=259357782, + message="RegionSetLabelsRequest", + ) + request_id: str = proto.Field( + proto.STRING, + number=37109963, + optional=True, + ) + resource: str = proto.Field( + proto.STRING, + number=195806222, + ) + + +class SetLabelsInterconnectRequest(proto.Message): + r"""A request message for Interconnects.SetLabels. See the method description for details. Attributes: @@ -98207,188 +99635,8 @@ class SetLabelsImageRequest(proto.Message): ) -class SetLabelsInstanceRequest(proto.Message): - r"""A request message for Instances.SetLabels. See the method - description for details. - - - .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields - - Attributes: - instance (str): - Name of the instance scoping this request. - instances_set_labels_request_resource (google.cloud.compute_v1.types.InstancesSetLabelsRequest): - The body resource for this request - project (str): - Project ID for this request. - request_id (str): - An optional request ID to identify requests. - Specify a unique request ID so that if you must - retry your request, the server will know to - ignore the request if it has already been - completed. For example, consider a situation - where you make an initial request and the - request times out. If you make the request again - with the same request ID, the server can check - if original operation with the same request ID - was received, and if so, will ignore the second - request. This prevents clients from accidentally - creating duplicate commitments. The request ID - must be a valid UUID with the exception that - zero UUID is not supported ( - 00000000-0000-0000-0000-000000000000). - - This field is a member of `oneof`_ ``_request_id``. - zone (str): - The name of the zone for this request. - """ - - instance: str = proto.Field( - proto.STRING, - number=18257045, - ) - instances_set_labels_request_resource: "InstancesSetLabelsRequest" = proto.Field( - proto.MESSAGE, - number=207749344, - message="InstancesSetLabelsRequest", - ) - project: str = proto.Field( - proto.STRING, - number=227560217, - ) - request_id: str = proto.Field( - proto.STRING, - number=37109963, - optional=True, - ) - zone: str = proto.Field( - proto.STRING, - number=3744684, - ) - - -class SetLabelsInstantSnapshotRequest(proto.Message): - r"""A request message for InstantSnapshots.SetLabels. See the - method description for details. - - - .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields - - Attributes: - project (str): - Project ID for this request. - request_id (str): - An optional request ID to identify requests. - Specify a unique request ID so that if you must - retry your request, the server will know to - ignore the request if it has already been - completed. For example, consider a situation - where you make an initial request and the - request times out. If you make the request again - with the same request ID, the server can check - if original operation with the same request ID - was received, and if so, will ignore the second - request. This prevents clients from accidentally - creating duplicate commitments. The request ID - must be a valid UUID with the exception that - zero UUID is not supported ( - 00000000-0000-0000-0000-000000000000). - - This field is a member of `oneof`_ ``_request_id``. - resource (str): - Name or id of the resource for this request. - zone (str): - The name of the zone for this request. - zone_set_labels_request_resource (google.cloud.compute_v1.types.ZoneSetLabelsRequest): - The body resource for this request - """ - - project: str = proto.Field( - proto.STRING, - number=227560217, - ) - request_id: str = proto.Field( - proto.STRING, - number=37109963, - optional=True, - ) - resource: str = proto.Field( - proto.STRING, - number=195806222, - ) - zone: str = proto.Field( - proto.STRING, - number=3744684, - ) - zone_set_labels_request_resource: "ZoneSetLabelsRequest" = proto.Field( - proto.MESSAGE, - number=364950798, - message="ZoneSetLabelsRequest", - ) - - -class SetLabelsInterconnectAttachmentRequest(proto.Message): - r"""A request message for InterconnectAttachments.SetLabels. See - the method description for details. - - - .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields - - Attributes: - project (str): - Project ID for this request. - region (str): - The region for this request. - region_set_labels_request_resource (google.cloud.compute_v1.types.RegionSetLabelsRequest): - The body resource for this request - request_id (str): - An optional request ID to identify requests. - Specify a unique request ID so that if you must - retry your request, the server will know to - ignore the request if it has already been - completed. For example, consider a situation - where you make an initial request and the - request times out. If you make the request again - with the same request ID, the server can check - if original operation with the same request ID - was received, and if so, will ignore the second - request. This prevents clients from accidentally - creating duplicate commitments. The request ID - must be a valid UUID with the exception that - zero UUID is not supported ( - 00000000-0000-0000-0000-000000000000). - - This field is a member of `oneof`_ ``_request_id``. - resource (str): - Name or id of the resource for this request. - """ - - project: str = proto.Field( - proto.STRING, - number=227560217, - ) - region: str = proto.Field( - proto.STRING, - number=138946292, - ) - region_set_labels_request_resource: "RegionSetLabelsRequest" = proto.Field( - proto.MESSAGE, - number=259357782, - message="RegionSetLabelsRequest", - ) - request_id: str = proto.Field( - proto.STRING, - number=37109963, - optional=True, - ) - resource: str = proto.Field( - proto.STRING, - number=195806222, - ) - - -class SetLabelsInterconnectRequest(proto.Message): - r"""A request message for Interconnects.SetLabels. See the method +class SetLabelsMachineImageRequest(proto.Message): + r"""A request message for MachineImages.SetLabels. See the method description for details. Attributes: @@ -101273,6 +102521,7 @@ class Snapshot(proto.Message): r"""Represents a Persistent Disk Snapshot resource. You can use snapshots to back up data on a regular interval. For more information, read Creating persistent disk snapshots. + LINT.IfChange .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields @@ -101331,6 +102580,12 @@ class Snapshot(proto.Message): from source disk. This field is a member of `oneof`_ ``_enable_confidential_compute``. + guest_flush (bool): + [Input Only] Whether to attempt an application consistent + snapshot by informing the OS to prepare for the snapshot + process. + + This field is a member of `oneof`_ ``_guest_flush``. guest_os_features (MutableSequence[google.cloud.compute_v1.types.GuestOsFeature]): [Output Only] A list of features to enable on the guest operating system. Applicable only for bootable images. Read @@ -101637,6 +102892,11 @@ class StorageBytesStatus(proto.Enum): number=102135228, optional=True, ) + guest_flush: bool = proto.Field( + proto.BOOL, + number=385550813, + optional=True, + ) guest_os_features: MutableSequence["GuestOsFeature"] = proto.RepeatedField( proto.MESSAGE, number=79294545, @@ -105455,24 +106715,8 @@ class Subnetwork(proto.Message): This field is a member of `oneof`_ ``_private_ipv6_google_access``. purpose (str): - The purpose of the resource. This field can be either - PRIVATE, GLOBAL_MANAGED_PROXY, REGIONAL_MANAGED_PROXY, - PEER_MIGRATION, PRIVATE_SERVICE_CONNECT or PRIVATE_NAT. - PRIVATE is the default purpose for user-created subnets or - subnets that are automatically created in auto mode - networks. Subnets with purpose set to GLOBAL_MANAGED_PROXY - or REGIONAL_MANAGED_PROXY are user-created subnetworks that - are reserved for Envoy-based load balancers. A subnet with - purpose set to PRIVATE_SERVICE_CONNECT is used to publish - services using Private Service Connect. A subnet with - purpose set to PEER_MIGRATION is used for subnet migration - from one peered VPC to another. A subnet with purpose set to - PRIVATE_NAT is used for Private NAT IP address by Private - NAT Gateway. If unspecified, the subnet purpose defaults to - PRIVATE. The enableFlowLogs field isn't supported if the - subnet purpose field is set to GLOBAL_MANAGED_PROXY or - REGIONAL_MANAGED_PROXY. Check the Purpose enum for the list - of possible values. + Check the Purpose enum for the list of + possible values. This field is a member of `oneof`_ ``_purpose``. region (str): @@ -105605,21 +106849,7 @@ class PrivateIpv6GoogleAccess(proto.Enum): ENABLE_OUTBOUND_VM_ACCESS_TO_GOOGLE = 288210263 class Purpose(proto.Enum): - r"""The purpose of the resource. This field can be either PRIVATE, - GLOBAL_MANAGED_PROXY, REGIONAL_MANAGED_PROXY, PEER_MIGRATION, - PRIVATE_SERVICE_CONNECT or PRIVATE_NAT. PRIVATE is the default - purpose for user-created subnets or subnets that are automatically - created in auto mode networks. Subnets with purpose set to - GLOBAL_MANAGED_PROXY or REGIONAL_MANAGED_PROXY are user-created - subnetworks that are reserved for Envoy-based load balancers. A - subnet with purpose set to PRIVATE_SERVICE_CONNECT is used to - publish services using Private Service Connect. A subnet with - purpose set to PEER_MIGRATION is used for subnet migration from one - peered VPC to another. A subnet with purpose set to PRIVATE_NAT is - used for Private NAT IP address by Private NAT Gateway. If - unspecified, the subnet purpose defaults to PRIVATE. The - enableFlowLogs field isn't supported if the subnet purpose field is - set to GLOBAL_MANAGED_PROXY or REGIONAL_MANAGED_PROXY. + r""" Values: UNDEFINED_PURPOSE (0): @@ -113628,24 +114858,8 @@ class UsableSubnetwork(proto.Message): This field is a member of `oneof`_ ``_network``. purpose (str): - The purpose of the resource. This field can be either - PRIVATE, GLOBAL_MANAGED_PROXY, REGIONAL_MANAGED_PROXY, - PEER_MIGRATION, PRIVATE_SERVICE_CONNECT or PRIVATE_NAT. - PRIVATE is the default purpose for user-created subnets or - subnets that are automatically created in auto mode - networks. Subnets with purpose set to GLOBAL_MANAGED_PROXY - or REGIONAL_MANAGED_PROXY are user-created subnetworks that - are reserved for Envoy-based load balancers. A subnet with - purpose set to PRIVATE_SERVICE_CONNECT is used to publish - services using Private Service Connect. A subnet with - purpose set to PEER_MIGRATION is used for subnet migration - from one peered VPC to another. A subnet with purpose set to - PRIVATE_NAT is used for Private NAT IP address by Private - NAT Gateway. If unspecified, the subnet purpose defaults to - PRIVATE. The enableFlowLogs field isn't supported if the - subnet purpose field is set to GLOBAL_MANAGED_PROXY or - REGIONAL_MANAGED_PROXY. Check the Purpose enum for the list - of possible values. + Check the Purpose enum for the list of + possible values. This field is a member of `oneof`_ ``_purpose``. role (str): @@ -113701,21 +114915,7 @@ class Ipv6AccessType(proto.Enum): INTERNAL = 279295677 class Purpose(proto.Enum): - r"""The purpose of the resource. This field can be either PRIVATE, - GLOBAL_MANAGED_PROXY, REGIONAL_MANAGED_PROXY, PEER_MIGRATION, - PRIVATE_SERVICE_CONNECT or PRIVATE_NAT. PRIVATE is the default - purpose for user-created subnets or subnets that are automatically - created in auto mode networks. Subnets with purpose set to - GLOBAL_MANAGED_PROXY or REGIONAL_MANAGED_PROXY are user-created - subnetworks that are reserved for Envoy-based load balancers. A - subnet with purpose set to PRIVATE_SERVICE_CONNECT is used to - publish services using Private Service Connect. A subnet with - purpose set to PEER_MIGRATION is used for subnet migration from one - peered VPC to another. A subnet with purpose set to PRIVATE_NAT is - used for Private NAT IP address by Private NAT Gateway. If - unspecified, the subnet purpose defaults to PRIVATE. The - enableFlowLogs field isn't supported if the subnet purpose field is - set to GLOBAL_MANAGED_PROXY or REGIONAL_MANAGED_PROXY. + r""" Values: UNDEFINED_PURPOSE (0): @@ -115730,7 +116930,7 @@ class WaitZoneOperationRequest(proto.Message): class Warning(proto.Message): - r"""[Output Only] Informational warning message. + r"""Informational warning message. .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields diff --git a/packages/google-cloud-compute/samples/generated_samples/compute_v1_generated_machine_images_set_labels_sync.py b/packages/google-cloud-compute/samples/generated_samples/compute_v1_generated_machine_images_set_labels_sync.py new file mode 100644 index 000000000000..e83e2212c341 --- /dev/null +++ b/packages/google-cloud-compute/samples/generated_samples/compute_v1_generated_machine_images_set_labels_sync.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for SetLabels +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-compute + + +# [START compute_v1_generated_MachineImages_SetLabels_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import compute_v1 + + +def sample_set_labels(): + # Create a client + client = compute_v1.MachineImagesClient() + + # Initialize request argument(s) + request = compute_v1.SetLabelsMachineImageRequest( + project="project_value", + resource="resource_value", + ) + + # Make the request + response = client.set_labels(request=request) + + # Handle the response + print(response) + +# [END compute_v1_generated_MachineImages_SetLabels_sync] diff --git a/packages/google-cloud-compute/samples/generated_samples/compute_v1_generated_reservation_blocks_get_sync.py b/packages/google-cloud-compute/samples/generated_samples/compute_v1_generated_reservation_blocks_get_sync.py new file mode 100644 index 000000000000..93def680cf63 --- /dev/null +++ b/packages/google-cloud-compute/samples/generated_samples/compute_v1_generated_reservation_blocks_get_sync.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for Get +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-compute + + +# [START compute_v1_generated_ReservationBlocks_Get_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import compute_v1 + + +def sample_get(): + # Create a client + client = compute_v1.ReservationBlocksClient() + + # Initialize request argument(s) + request = compute_v1.GetReservationBlockRequest( + project="project_value", + reservation="reservation_value", + reservation_block="reservation_block_value", + zone="zone_value", + ) + + # Make the request + response = client.get(request=request) + + # Handle the response + print(response) + +# [END compute_v1_generated_ReservationBlocks_Get_sync] diff --git a/packages/google-cloud-compute/samples/generated_samples/compute_v1_generated_reservation_blocks_list_sync.py b/packages/google-cloud-compute/samples/generated_samples/compute_v1_generated_reservation_blocks_list_sync.py new file mode 100644 index 000000000000..cfe1ff6bfab4 --- /dev/null +++ b/packages/google-cloud-compute/samples/generated_samples/compute_v1_generated_reservation_blocks_list_sync.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for List +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-compute + + +# [START compute_v1_generated_ReservationBlocks_List_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import compute_v1 + + +def sample_list(): + # Create a client + client = compute_v1.ReservationBlocksClient() + + # Initialize request argument(s) + request = compute_v1.ListReservationBlocksRequest( + project="project_value", + reservation="reservation_value", + zone="zone_value", + ) + + # Make the request + page_result = client.list(request=request) + + # Handle the response + for response in page_result: + print(response) + +# [END compute_v1_generated_ReservationBlocks_List_sync] diff --git a/packages/google-cloud-compute/samples/generated_samples/compute_v1_generated_reservation_blocks_perform_maintenance_sync.py b/packages/google-cloud-compute/samples/generated_samples/compute_v1_generated_reservation_blocks_perform_maintenance_sync.py new file mode 100644 index 000000000000..08467538c164 --- /dev/null +++ b/packages/google-cloud-compute/samples/generated_samples/compute_v1_generated_reservation_blocks_perform_maintenance_sync.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for PerformMaintenance +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-compute + + +# [START compute_v1_generated_ReservationBlocks_PerformMaintenance_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import compute_v1 + + +def sample_perform_maintenance(): + # Create a client + client = compute_v1.ReservationBlocksClient() + + # Initialize request argument(s) + request = compute_v1.PerformMaintenanceReservationBlockRequest( + project="project_value", + reservation="reservation_value", + reservation_block="reservation_block_value", + zone="zone_value", + ) + + # Make the request + response = client.perform_maintenance(request=request) + + # Handle the response + print(response) + +# [END compute_v1_generated_ReservationBlocks_PerformMaintenance_sync] diff --git a/packages/google-cloud-compute/samples/generated_samples/compute_v1_generated_reservations_perform_maintenance_sync.py b/packages/google-cloud-compute/samples/generated_samples/compute_v1_generated_reservations_perform_maintenance_sync.py new file mode 100644 index 000000000000..c8a9995911f6 --- /dev/null +++ b/packages/google-cloud-compute/samples/generated_samples/compute_v1_generated_reservations_perform_maintenance_sync.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for PerformMaintenance +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-compute + + +# [START compute_v1_generated_Reservations_PerformMaintenance_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import compute_v1 + + +def sample_perform_maintenance(): + # Create a client + client = compute_v1.ReservationsClient() + + # Initialize request argument(s) + request = compute_v1.PerformMaintenanceReservationRequest( + project="project_value", + reservation="reservation_value", + zone="zone_value", + ) + + # Make the request + response = client.perform_maintenance(request=request) + + # Handle the response + print(response) + +# [END compute_v1_generated_Reservations_PerformMaintenance_sync] diff --git a/packages/google-cloud-compute/samples/generated_samples/snippet_metadata_google.cloud.compute.v1.json b/packages/google-cloud-compute/samples/generated_samples/snippet_metadata_google.cloud.compute.v1.json index 78a7aafebe90..2d34417e8b5e 100644 --- a/packages/google-cloud-compute/samples/generated_samples/snippet_metadata_google.cloud.compute.v1.json +++ b/packages/google-cloud-compute/samples/generated_samples/snippet_metadata_google.cloud.compute.v1.json @@ -25671,6 +25671,94 @@ ], "title": "compute_v1_generated_machine_images_set_iam_policy_sync.py" }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.compute_v1.MachineImagesClient", + "shortName": "MachineImagesClient" + }, + "fullName": "google.cloud.compute_v1.MachineImagesClient.set_labels", + "method": { + "fullName": "google.cloud.compute.v1.MachineImages.SetLabels", + "service": { + "fullName": "google.cloud.compute.v1.MachineImages", + "shortName": "MachineImages" + }, + "shortName": "SetLabels" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.compute_v1.types.SetLabelsMachineImageRequest" + }, + { + "name": "project", + "type": "str" + }, + { + "name": "resource", + "type": "str" + }, + { + "name": "global_set_labels_request_resource", + "type": "google.cloud.compute_v1.types.GlobalSetLabelsRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.api_core.extended_operation.ExtendedOperation", + "shortName": "set_labels" + }, + "description": "Sample for SetLabels", + "file": "compute_v1_generated_machine_images_set_labels_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "compute_v1_generated_MachineImages_SetLabels_sync", + "segments": [ + { + "end": 52, + "start": 27, + "type": "FULL" + }, + { + "end": 52, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 46, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 49, + "start": 47, + "type": "REQUEST_EXECUTION" + }, + { + "end": 53, + "start": 50, + "type": "RESPONSE_HANDLING" + } + ], + "title": "compute_v1_generated_machine_images_set_labels_sync.py" + }, { "canonical": true, "clientMethod": { @@ -51439,6 +51527,282 @@ ], "title": "compute_v1_generated_regions_list_sync.py" }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.compute_v1.ReservationBlocksClient", + "shortName": "ReservationBlocksClient" + }, + "fullName": "google.cloud.compute_v1.ReservationBlocksClient.get", + "method": { + "fullName": "google.cloud.compute.v1.ReservationBlocks.Get", + "service": { + "fullName": "google.cloud.compute.v1.ReservationBlocks", + "shortName": "ReservationBlocks" + }, + "shortName": "Get" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.compute_v1.types.GetReservationBlockRequest" + }, + { + "name": "project", + "type": "str" + }, + { + "name": "zone", + "type": "str" + }, + { + "name": "reservation", + "type": "str" + }, + { + "name": "reservation_block", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.cloud.compute_v1.types.ReservationBlocksGetResponse", + "shortName": "get" + }, + "description": "Sample for Get", + "file": "compute_v1_generated_reservation_blocks_get_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "compute_v1_generated_ReservationBlocks_Get_sync", + "segments": [ + { + "end": 54, + "start": 27, + "type": "FULL" + }, + { + "end": 54, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 48, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 51, + "start": 49, + "type": "REQUEST_EXECUTION" + }, + { + "end": 55, + "start": 52, + "type": "RESPONSE_HANDLING" + } + ], + "title": "compute_v1_generated_reservation_blocks_get_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.compute_v1.ReservationBlocksClient", + "shortName": "ReservationBlocksClient" + }, + "fullName": "google.cloud.compute_v1.ReservationBlocksClient.list", + "method": { + "fullName": "google.cloud.compute.v1.ReservationBlocks.List", + "service": { + "fullName": "google.cloud.compute.v1.ReservationBlocks", + "shortName": "ReservationBlocks" + }, + "shortName": "List" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.compute_v1.types.ListReservationBlocksRequest" + }, + { + "name": "project", + "type": "str" + }, + { + "name": "zone", + "type": "str" + }, + { + "name": "reservation", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.cloud.compute_v1.services.reservation_blocks.pagers.ListPager", + "shortName": "list" + }, + "description": "Sample for List", + "file": "compute_v1_generated_reservation_blocks_list_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "compute_v1_generated_ReservationBlocks_List_sync", + "segments": [ + { + "end": 54, + "start": 27, + "type": "FULL" + }, + { + "end": 54, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 47, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 50, + "start": 48, + "type": "REQUEST_EXECUTION" + }, + { + "end": 55, + "start": 51, + "type": "RESPONSE_HANDLING" + } + ], + "title": "compute_v1_generated_reservation_blocks_list_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.compute_v1.ReservationBlocksClient", + "shortName": "ReservationBlocksClient" + }, + "fullName": "google.cloud.compute_v1.ReservationBlocksClient.perform_maintenance", + "method": { + "fullName": "google.cloud.compute.v1.ReservationBlocks.PerformMaintenance", + "service": { + "fullName": "google.cloud.compute.v1.ReservationBlocks", + "shortName": "ReservationBlocks" + }, + "shortName": "PerformMaintenance" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.compute_v1.types.PerformMaintenanceReservationBlockRequest" + }, + { + "name": "project", + "type": "str" + }, + { + "name": "zone", + "type": "str" + }, + { + "name": "reservation", + "type": "str" + }, + { + "name": "reservation_block", + "type": "str" + }, + { + "name": "reservations_blocks_perform_maintenance_request_resource", + "type": "google.cloud.compute_v1.types.ReservationsBlocksPerformMaintenanceRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.api_core.extended_operation.ExtendedOperation", + "shortName": "perform_maintenance" + }, + "description": "Sample for PerformMaintenance", + "file": "compute_v1_generated_reservation_blocks_perform_maintenance_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "compute_v1_generated_ReservationBlocks_PerformMaintenance_sync", + "segments": [ + { + "end": 54, + "start": 27, + "type": "FULL" + }, + { + "end": 54, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 48, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 51, + "start": 49, + "type": "REQUEST_EXECUTION" + }, + { + "end": 55, + "start": 52, + "type": "RESPONSE_HANDLING" + } + ], + "title": "compute_v1_generated_reservation_blocks_perform_maintenance_sync.py" + }, { "canonical": true, "clientMethod": { @@ -51955,6 +52319,98 @@ ], "title": "compute_v1_generated_reservations_list_sync.py" }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.compute_v1.ReservationsClient", + "shortName": "ReservationsClient" + }, + "fullName": "google.cloud.compute_v1.ReservationsClient.perform_maintenance", + "method": { + "fullName": "google.cloud.compute.v1.Reservations.PerformMaintenance", + "service": { + "fullName": "google.cloud.compute.v1.Reservations", + "shortName": "Reservations" + }, + "shortName": "PerformMaintenance" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.compute_v1.types.PerformMaintenanceReservationRequest" + }, + { + "name": "project", + "type": "str" + }, + { + "name": "zone", + "type": "str" + }, + { + "name": "reservation", + "type": "str" + }, + { + "name": "reservations_perform_maintenance_request_resource", + "type": "google.cloud.compute_v1.types.ReservationsPerformMaintenanceRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.api_core.extended_operation.ExtendedOperation", + "shortName": "perform_maintenance" + }, + "description": "Sample for PerformMaintenance", + "file": "compute_v1_generated_reservations_perform_maintenance_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "compute_v1_generated_Reservations_PerformMaintenance_sync", + "segments": [ + { + "end": 53, + "start": 27, + "type": "FULL" + }, + { + "end": 53, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 47, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 50, + "start": 48, + "type": "REQUEST_EXECUTION" + }, + { + "end": 54, + "start": 51, + "type": "RESPONSE_HANDLING" + } + ], + "title": "compute_v1_generated_reservations_perform_maintenance_sync.py" + }, { "canonical": true, "clientMethod": { diff --git a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_backend_services.py b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_backend_services.py index c43a9d6dfa4e..6b9bcad7f2d9 100644 --- a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_backend_services.py +++ b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_backend_services.py @@ -6925,6 +6925,8 @@ def test_get_rest_call_success(request_type): description="description_value", edge_security_policy="edge_security_policy_value", enable_c_d_n=True, + external_managed_migration_state="external_managed_migration_state_value", + external_managed_migration_testing_percentage=0.47540000000000004, fingerprint="fingerprint_value", health_checks=["health_checks_value"], id=205, @@ -6968,6 +6970,15 @@ def test_get_rest_call_success(request_type): assert response.description == "description_value" assert response.edge_security_policy == "edge_security_policy_value" assert response.enable_c_d_n is True + assert ( + response.external_managed_migration_state + == "external_managed_migration_state_value" + ) + assert math.isclose( + response.external_managed_migration_testing_percentage, + 0.47540000000000004, + rel_tol=1e-6, + ) assert response.fingerprint == "fingerprint_value" assert response.health_checks == ["health_checks_value"] assert response.id == 205 @@ -7520,6 +7531,8 @@ def test_insert_rest_call_success(request_type): "description": "description_value", "edge_security_policy": "edge_security_policy_value", "enable_c_d_n": True, + "external_managed_migration_state": "external_managed_migration_state_value", + "external_managed_migration_testing_percentage": 0.47540000000000004, "failover_policy": { "disable_connection_drain_on_failover": True, "drop_traffic_if_unhealthy": True, @@ -8199,6 +8212,8 @@ def test_patch_rest_call_success(request_type): "description": "description_value", "edge_security_policy": "edge_security_policy_value", "enable_c_d_n": True, + "external_managed_migration_state": "external_managed_migration_state_value", + "external_managed_migration_testing_percentage": 0.47540000000000004, "failover_policy": { "disable_connection_drain_on_failover": True, "drop_traffic_if_unhealthy": True, @@ -9563,6 +9578,8 @@ def test_update_rest_call_success(request_type): "description": "description_value", "edge_security_policy": "edge_security_policy_value", "enable_c_d_n": True, + "external_managed_migration_state": "external_managed_migration_state_value", + "external_managed_migration_testing_percentage": 0.47540000000000004, "failover_policy": { "disable_connection_drain_on_failover": True, "drop_traffic_if_unhealthy": True, diff --git a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_disks.py b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_disks.py index c1f009be39b6..e7afec8ca2da 100644 --- a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_disks.py +++ b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_disks.py @@ -8139,6 +8139,7 @@ def test_create_snapshot_rest_call_success(request_type): "disk_size_gb": 1261, "download_bytes": 1502, "enable_confidential_compute": True, + "guest_flush": True, "guest_os_features": [{"type_": "type__value"}], "id": 205, "kind": "kind_value", diff --git a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_machine_images.py b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_machine_images.py index aa0fd616ea24..e82785e825ef 100644 --- a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_machine_images.py +++ b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_machine_images.py @@ -2600,6 +2600,414 @@ def test_set_iam_policy_rest_flattened_error(transport: str = "rest"): ) +def test_set_labels_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = MachineImagesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.set_labels in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.set_labels] = mock_rpc + + request = {} + client.set_labels(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.set_labels(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_set_labels_rest_required_fields( + request_type=compute.SetLabelsMachineImageRequest, +): + transport_class = transports.MachineImagesRestTransport + + request_init = {} + request_init["project"] = "" + request_init["resource"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).set_labels._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["project"] = "project_value" + jsonified_request["resource"] = "resource_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).set_labels._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "project" in jsonified_request + assert jsonified_request["project"] == "project_value" + assert "resource" in jsonified_request + assert jsonified_request["resource"] == "resource_value" + + client = MachineImagesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = compute.Operation() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = compute.Operation.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.set_labels(request) + + expected_params = [] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_set_labels_rest_unset_required_fields(): + transport = transports.MachineImagesRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.set_labels._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "globalSetLabelsRequestResource", + "project", + "resource", + ) + ) + ) + + +def test_set_labels_rest_flattened(): + client = MachineImagesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = compute.Operation() + + # get arguments that satisfy an http rule for this method + sample_request = {"project": "sample1", "resource": "sample2"} + + # get truthy value for each flattened field + mock_args = dict( + project="project_value", + resource="resource_value", + global_set_labels_request_resource=compute.GlobalSetLabelsRequest( + label_fingerprint="label_fingerprint_value" + ), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = compute.Operation.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + client.set_labels(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/compute/v1/projects/{project}/global/machineImages/{resource}/setLabels" + % client.transport._host, + args[1], + ) + + +def test_set_labels_rest_flattened_error(transport: str = "rest"): + client = MachineImagesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.set_labels( + compute.SetLabelsMachineImageRequest(), + project="project_value", + resource="resource_value", + global_set_labels_request_resource=compute.GlobalSetLabelsRequest( + label_fingerprint="label_fingerprint_value" + ), + ) + + +def test_set_labels_unary_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = MachineImagesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.set_labels in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.set_labels] = mock_rpc + + request = {} + client.set_labels_unary(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.set_labels_unary(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_set_labels_unary_rest_required_fields( + request_type=compute.SetLabelsMachineImageRequest, +): + transport_class = transports.MachineImagesRestTransport + + request_init = {} + request_init["project"] = "" + request_init["resource"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).set_labels._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["project"] = "project_value" + jsonified_request["resource"] = "resource_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).set_labels._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "project" in jsonified_request + assert jsonified_request["project"] == "project_value" + assert "resource" in jsonified_request + assert jsonified_request["resource"] == "resource_value" + + client = MachineImagesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = compute.Operation() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = compute.Operation.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.set_labels_unary(request) + + expected_params = [] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_set_labels_unary_rest_unset_required_fields(): + transport = transports.MachineImagesRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.set_labels._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "globalSetLabelsRequestResource", + "project", + "resource", + ) + ) + ) + + +def test_set_labels_unary_rest_flattened(): + client = MachineImagesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = compute.Operation() + + # get arguments that satisfy an http rule for this method + sample_request = {"project": "sample1", "resource": "sample2"} + + # get truthy value for each flattened field + mock_args = dict( + project="project_value", + resource="resource_value", + global_set_labels_request_resource=compute.GlobalSetLabelsRequest( + label_fingerprint="label_fingerprint_value" + ), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = compute.Operation.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + client.set_labels_unary(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/compute/v1/projects/{project}/global/machineImages/{resource}/setLabels" + % client.transport._host, + args[1], + ) + + +def test_set_labels_unary_rest_flattened_error(transport: str = "rest"): + client = MachineImagesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.set_labels_unary( + compute.SetLabelsMachineImageRequest(), + project="project_value", + resource="resource_value", + global_set_labels_request_resource=compute.GlobalSetLabelsRequest( + label_fingerprint="label_fingerprint_value" + ), + ) + + def test_test_iam_permissions_rest_use_cached_wrapped_rpc(): # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, # instead of constructing them on each call @@ -3101,6 +3509,7 @@ def test_get_rest_call_success(request_type): guest_flush=True, id=205, kind="kind_value", + label_fingerprint="label_fingerprint_value", name="name_value", satisfies_pzi=True, satisfies_pzs=True, @@ -3130,6 +3539,7 @@ def test_get_rest_call_success(request_type): assert response.guest_flush is True assert response.id == 205 assert response.kind == "kind_value" + assert response.label_fingerprint == "label_fingerprint_value" assert response.name == "name_value" assert response.satisfies_pzi is True assert response.satisfies_pzs is True @@ -3552,6 +3962,8 @@ def test_insert_rest_call_success(request_type): }, }, "kind": "kind_value", + "label_fingerprint": "label_fingerprint_value", + "labels": {}, "machine_image_encryption_key": {}, "name": "name_value", "satisfies_pzi": True, @@ -4186,6 +4598,252 @@ def test_set_iam_policy_rest_interceptors(null_interceptor): post_with_metadata.assert_called_once() +def test_set_labels_rest_bad_request(request_type=compute.SetLabelsMachineImageRequest): + client = MachineImagesClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + # send a request that will satisfy transcoding + request_init = {"project": "sample1", "resource": "sample2"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = mock.Mock() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.set_labels(request) + + +@pytest.mark.parametrize( + "request_type", + [ + compute.SetLabelsMachineImageRequest, + dict, + ], +) +def test_set_labels_rest_call_success(request_type): + client = MachineImagesClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + # send a request that will satisfy transcoding + request_init = {"project": "sample1", "resource": "sample2"} + request_init["global_set_labels_request_resource"] = { + "label_fingerprint": "label_fingerprint_value", + "labels": {}, + } + # The version of a generated dependency at test runtime may differ from the version used during generation. + # Delete any fields which are not present in the current runtime dependency + # See https://github.com/googleapis/gapic-generator-python/issues/1748 + + # Determine if the message type is proto-plus or protobuf + test_field = compute.SetLabelsMachineImageRequest.meta.fields[ + "global_set_labels_request_resource" + ] + + def get_message_fields(field): + # Given a field which is a message (composite type), return a list with + # all the fields of the message. + # If the field is not a composite type, return an empty list. + message_fields = [] + + if hasattr(field, "message") and field.message: + is_field_type_proto_plus_type = not hasattr(field.message, "DESCRIPTOR") + + if is_field_type_proto_plus_type: + message_fields = field.message.meta.fields.values() + # Add `# pragma: NO COVER` because there may not be any `*_pb2` field types + else: # pragma: NO COVER + message_fields = field.message.DESCRIPTOR.fields + return message_fields + + runtime_nested_fields = [ + (field.name, nested_field.name) + for field in get_message_fields(test_field) + for nested_field in get_message_fields(field) + ] + + subfields_not_in_runtime = [] + + # For each item in the sample request, create a list of sub fields which are not present at runtime + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for field, value in request_init[ + "global_set_labels_request_resource" + ].items(): # pragma: NO COVER + result = None + is_repeated = False + # For repeated fields + if isinstance(value, list) and len(value): + is_repeated = True + result = value[0] + # For fields where the type is another message + if isinstance(value, dict): + result = value + + if result and hasattr(result, "keys"): + for subfield in result.keys(): + if (field, subfield) not in runtime_nested_fields: + subfields_not_in_runtime.append( + { + "field": field, + "subfield": subfield, + "is_repeated": is_repeated, + } + ) + + # Remove fields from the sample request which are not present in the runtime version of the dependency + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for subfield_to_delete in subfields_not_in_runtime: # pragma: NO COVER + field = subfield_to_delete.get("field") + field_repeated = subfield_to_delete.get("is_repeated") + subfield = subfield_to_delete.get("subfield") + if subfield: + if field_repeated: + for i in range( + 0, len(request_init["global_set_labels_request_resource"][field]) + ): + del request_init["global_set_labels_request_resource"][field][i][ + subfield + ] + else: + del request_init["global_set_labels_request_resource"][field][subfield] + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = compute.Operation( + client_operation_id="client_operation_id_value", + creation_timestamp="creation_timestamp_value", + description="description_value", + end_time="end_time_value", + http_error_message="http_error_message_value", + http_error_status_code=2374, + id=205, + insert_time="insert_time_value", + kind="kind_value", + name="name_value", + operation_group_id="operation_group_id_value", + operation_type="operation_type_value", + progress=885, + region="region_value", + self_link="self_link_value", + start_time="start_time_value", + status=compute.Operation.Status.DONE, + status_message="status_message_value", + target_id=947, + target_link="target_link_value", + user="user_value", + zone="zone_value", + ) + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = compute.Operation.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value.content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = client.set_labels(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, extended_operation.ExtendedOperation) + assert response.client_operation_id == "client_operation_id_value" + assert response.creation_timestamp == "creation_timestamp_value" + assert response.description == "description_value" + assert response.end_time == "end_time_value" + assert response.http_error_message == "http_error_message_value" + assert response.http_error_status_code == 2374 + assert response.id == 205 + assert response.insert_time == "insert_time_value" + assert response.kind == "kind_value" + assert response.name == "name_value" + assert response.operation_group_id == "operation_group_id_value" + assert response.operation_type == "operation_type_value" + assert response.progress == 885 + assert response.region == "region_value" + assert response.self_link == "self_link_value" + assert response.start_time == "start_time_value" + assert response.status == compute.Operation.Status.DONE + assert response.status_message == "status_message_value" + assert response.target_id == 947 + assert response.target_link == "target_link_value" + assert response.user == "user_value" + assert response.zone == "zone_value" + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_set_labels_rest_interceptors(null_interceptor): + transport = transports.MachineImagesRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.MachineImagesRestInterceptor(), + ) + client = MachineImagesClient(transport=transport) + + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.MachineImagesRestInterceptor, "post_set_labels" + ) as post, mock.patch.object( + transports.MachineImagesRestInterceptor, "post_set_labels_with_metadata" + ) as post_with_metadata, mock.patch.object( + transports.MachineImagesRestInterceptor, "pre_set_labels" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = compute.SetLabelsMachineImageRequest.pb( + compute.SetLabelsMachineImageRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = compute.Operation.to_json(compute.Operation()) + req.return_value.content = return_value + + request = compute.SetLabelsMachineImageRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = compute.Operation() + post_with_metadata.return_value = compute.Operation(), metadata + + client.set_labels( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + def test_test_iam_permissions_rest_bad_request( request_type=compute.TestIamPermissionsMachineImageRequest, ): @@ -4521,6 +5179,26 @@ def test_set_iam_policy_empty_call_rest(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_set_labels_unary_empty_call_rest(): + client = MachineImagesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.set_labels), "__call__") as call: + client.set_labels_unary(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = compute.SetLabelsMachineImageRequest() + + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. def test_test_iam_permissions_empty_call_rest(): @@ -4571,6 +5249,7 @@ def test_machine_images_base_transport(): "insert", "list", "set_iam_policy", + "set_labels", "test_iam_permissions", ) for method in methods: @@ -4727,6 +5406,9 @@ def test_machine_images_client_transport_session_collision(transport_name): session1 = client1.transport.set_iam_policy._session session2 = client2.transport.set_iam_policy._session assert session1 != session2 + session1 = client1.transport.set_labels._session + session2 = client2.transport.set_labels._session + assert session1 != session2 session1 = client1.transport.test_iam_permissions._session session2 = client2.transport.test_iam_permissions._session assert session1 != session2 diff --git a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_region_backend_services.py b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_region_backend_services.py index dc2f69e065cb..76eddec54c4f 100644 --- a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_region_backend_services.py +++ b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_region_backend_services.py @@ -5039,6 +5039,8 @@ def test_get_rest_call_success(request_type): description="description_value", edge_security_policy="edge_security_policy_value", enable_c_d_n=True, + external_managed_migration_state="external_managed_migration_state_value", + external_managed_migration_testing_percentage=0.47540000000000004, fingerprint="fingerprint_value", health_checks=["health_checks_value"], id=205, @@ -5082,6 +5084,15 @@ def test_get_rest_call_success(request_type): assert response.description == "description_value" assert response.edge_security_policy == "edge_security_policy_value" assert response.enable_c_d_n is True + assert ( + response.external_managed_migration_state + == "external_managed_migration_state_value" + ) + assert math.isclose( + response.external_managed_migration_testing_percentage, + 0.47540000000000004, + rel_tol=1e-6, + ) assert response.fingerprint == "fingerprint_value" assert response.health_checks == ["health_checks_value"] assert response.id == 205 @@ -5645,6 +5656,8 @@ def test_insert_rest_call_success(request_type): "description": "description_value", "edge_security_policy": "edge_security_policy_value", "enable_c_d_n": True, + "external_managed_migration_state": "external_managed_migration_state_value", + "external_managed_migration_testing_percentage": 0.47540000000000004, "failover_policy": { "disable_connection_drain_on_failover": True, "drop_traffic_if_unhealthy": True, @@ -6333,6 +6346,8 @@ def test_patch_rest_call_success(request_type): "description": "description_value", "edge_security_policy": "edge_security_policy_value", "enable_c_d_n": True, + "external_managed_migration_state": "external_managed_migration_state_value", + "external_managed_migration_testing_percentage": 0.47540000000000004, "failover_policy": { "disable_connection_drain_on_failover": True, "drop_traffic_if_unhealthy": True, @@ -7468,6 +7483,8 @@ def test_update_rest_call_success(request_type): "description": "description_value", "edge_security_policy": "edge_security_policy_value", "enable_c_d_n": True, + "external_managed_migration_state": "external_managed_migration_state_value", + "external_managed_migration_testing_percentage": 0.47540000000000004, "failover_policy": { "disable_connection_drain_on_failover": True, "drop_traffic_if_unhealthy": True, diff --git a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_region_commitments.py b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_region_commitments.py index 3d00326b01af..8ac09ff4b95e 100644 --- a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_region_commitments.py +++ b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_region_commitments.py @@ -3040,19 +3040,38 @@ def test_insert_rest_call_success(request_type): }, "commitment": "commitment_value", "creation_timestamp": "creation_timestamp_value", + "deployment_type": "deployment_type_value", "description": "description_value", "id": 205, "kind": "kind_value", + "linked_commitments": [ + "linked_commitments_value1", + "linked_commitments_value2", + ], "name": "name_value", "reservation_sharing_policy": { "service_share_type": "service_share_type_value" }, "resource_policies": {}, "resource_status": { + "reservation_block_count": 2468, + "reservation_maintenance": { + "maintenance_ongoing_count": 2651, + "maintenance_pending_count": 2639, + "scheduling_type": "scheduling_type_value", + "upcoming_group_maintenance": { + "can_reschedule": True, + "latest_window_start_time": "latest_window_start_time_value", + "maintenance_status": "maintenance_status_value", + "type_": "type__value", + "window_end_time": "window_end_time_value", + "window_start_time": "window_start_time_value", + }, + }, "specific_sku_allocation": { "source_instance_template_id": "source_instance_template_id_value", "utilizations": {}, - } + }, }, "satisfies_pzs": True, "self_link": "self_link_value", @@ -3508,19 +3527,38 @@ def test_update_rest_call_success(request_type): }, "commitment": "commitment_value", "creation_timestamp": "creation_timestamp_value", + "deployment_type": "deployment_type_value", "description": "description_value", "id": 205, "kind": "kind_value", + "linked_commitments": [ + "linked_commitments_value1", + "linked_commitments_value2", + ], "name": "name_value", "reservation_sharing_policy": { "service_share_type": "service_share_type_value" }, "resource_policies": {}, "resource_status": { + "reservation_block_count": 2468, + "reservation_maintenance": { + "maintenance_ongoing_count": 2651, + "maintenance_pending_count": 2639, + "scheduling_type": "scheduling_type_value", + "upcoming_group_maintenance": { + "can_reschedule": True, + "latest_window_start_time": "latest_window_start_time_value", + "maintenance_status": "maintenance_status_value", + "type_": "type__value", + "window_end_time": "window_end_time_value", + "window_start_time": "window_start_time_value", + }, + }, "specific_sku_allocation": { "source_instance_template_id": "source_instance_template_id_value", "utilizations": {}, - } + }, }, "satisfies_pzs": True, "self_link": "self_link_value", diff --git a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_region_disks.py b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_region_disks.py index 2305675a446b..ea653eca53f0 100644 --- a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_region_disks.py +++ b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_region_disks.py @@ -7769,6 +7769,7 @@ def test_create_snapshot_rest_call_success(request_type): "disk_size_gb": 1261, "download_bytes": 1502, "enable_confidential_compute": True, + "guest_flush": True, "guest_os_features": [{"type_": "type__value"}], "id": 205, "kind": "kind_value", diff --git a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_reservation_blocks.py b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_reservation_blocks.py new file mode 100644 index 000000000000..26373f97eba1 --- /dev/null +++ b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_reservation_blocks.py @@ -0,0 +1,2981 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + +# try/except added for compatibility with python < 3.8 +try: + from unittest import mock + from unittest.mock import AsyncMock # pragma: NO COVER +except ImportError: # pragma: NO COVER + import mock + +from collections.abc import AsyncIterable, Iterable +import json +import math + +from google.api_core import api_core_version +from google.protobuf import json_format +import grpc +from grpc.experimental import aio +from proto.marshal.rules import wrappers +from proto.marshal.rules.dates import DurationRule, TimestampRule +import pytest +from requests import PreparedRequest, Request, Response +from requests.sessions import Session + +try: + from google.auth.aio import credentials as ga_credentials_async + + HAS_GOOGLE_AUTH_AIO = True +except ImportError: # pragma: NO COVER + HAS_GOOGLE_AUTH_AIO = False + +from google.api_core import ( + future, + gapic_v1, + grpc_helpers, + grpc_helpers_async, + path_template, +) +from google.api_core import client_options +from google.api_core import exceptions as core_exceptions +from google.api_core import extended_operation # type: ignore +from google.api_core import retry as retries +import google.auth +from google.auth import credentials as ga_credentials +from google.auth.exceptions import MutualTLSChannelError +from google.oauth2 import service_account + +from google.cloud.compute_v1.services.reservation_blocks import ( + ReservationBlocksClient, + pagers, + transports, +) +from google.cloud.compute_v1.types import compute + +CRED_INFO_JSON = { + "credential_source": "/path/to/file", + "credential_type": "service account credentials", + "principal": "service-account@example.com", +} +CRED_INFO_STRING = json.dumps(CRED_INFO_JSON) + + +async def mock_async_gen(data, chunk_size=1): + for i in range(0, len(data)): # pragma: NO COVER + chunk = data[i : i + chunk_size] + yield chunk.encode("utf-8") + + +def client_cert_source_callback(): + return b"cert bytes", b"key bytes" + + +# TODO: use async auth anon credentials by default once the minimum version of google-auth is upgraded. +# See related issue: https://github.com/googleapis/gapic-generator-python/issues/2107. +def async_anonymous_credentials(): + if HAS_GOOGLE_AUTH_AIO: + return ga_credentials_async.AnonymousCredentials() + return ga_credentials.AnonymousCredentials() + + +# If default endpoint is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint(client): + return ( + "foo.googleapis.com" + if ("localhost" in client.DEFAULT_ENDPOINT) + else client.DEFAULT_ENDPOINT + ) + + +# If default endpoint template is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint template so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint_template(client): + return ( + "test.{UNIVERSE_DOMAIN}" + if ("localhost" in client._DEFAULT_ENDPOINT_TEMPLATE) + else client._DEFAULT_ENDPOINT_TEMPLATE + ) + + +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 ReservationBlocksClient._get_default_mtls_endpoint(None) is None + assert ( + ReservationBlocksClient._get_default_mtls_endpoint(api_endpoint) + == api_mtls_endpoint + ) + assert ( + ReservationBlocksClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + ReservationBlocksClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + ReservationBlocksClient._get_default_mtls_endpoint(sandbox_mtls_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + ReservationBlocksClient._get_default_mtls_endpoint(non_googleapi) + == non_googleapi + ) + + +def test__read_environment_variables(): + assert ReservationBlocksClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + assert ReservationBlocksClient._read_environment_variables() == ( + True, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + assert ReservationBlocksClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + ReservationBlocksClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + assert ReservationBlocksClient._read_environment_variables() == ( + False, + "never", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + assert ReservationBlocksClient._read_environment_variables() == ( + False, + "always", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}): + assert ReservationBlocksClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + ReservationBlocksClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_CLOUD_UNIVERSE_DOMAIN": "foo.com"}): + assert ReservationBlocksClient._read_environment_variables() == ( + False, + "auto", + "foo.com", + ) + + +def test__get_client_cert_source(): + mock_provided_cert_source = mock.Mock() + mock_default_cert_source = mock.Mock() + + assert ReservationBlocksClient._get_client_cert_source(None, False) is None + assert ( + ReservationBlocksClient._get_client_cert_source( + mock_provided_cert_source, False + ) + is None + ) + assert ( + ReservationBlocksClient._get_client_cert_source(mock_provided_cert_source, True) + == mock_provided_cert_source + ) + + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", return_value=True + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=mock_default_cert_source, + ): + assert ( + ReservationBlocksClient._get_client_cert_source(None, True) + is mock_default_cert_source + ) + assert ( + ReservationBlocksClient._get_client_cert_source( + mock_provided_cert_source, "true" + ) + is mock_provided_cert_source + ) + + +@mock.patch.object( + ReservationBlocksClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(ReservationBlocksClient), +) +def test__get_api_endpoint(): + api_override = "foo.com" + mock_client_cert_source = mock.Mock() + default_universe = ReservationBlocksClient._DEFAULT_UNIVERSE + default_endpoint = ReservationBlocksClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = ReservationBlocksClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + assert ( + ReservationBlocksClient._get_api_endpoint( + api_override, mock_client_cert_source, default_universe, "always" + ) + == api_override + ) + assert ( + ReservationBlocksClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "auto" + ) + == ReservationBlocksClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + ReservationBlocksClient._get_api_endpoint(None, None, default_universe, "auto") + == default_endpoint + ) + assert ( + ReservationBlocksClient._get_api_endpoint( + None, None, default_universe, "always" + ) + == ReservationBlocksClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + ReservationBlocksClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "always" + ) + == ReservationBlocksClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + ReservationBlocksClient._get_api_endpoint(None, None, mock_universe, "never") + == mock_endpoint + ) + assert ( + ReservationBlocksClient._get_api_endpoint(None, None, default_universe, "never") + == default_endpoint + ) + + with pytest.raises(MutualTLSChannelError) as excinfo: + ReservationBlocksClient._get_api_endpoint( + None, mock_client_cert_source, mock_universe, "auto" + ) + assert ( + str(excinfo.value) + == "mTLS is not supported in any universe other than googleapis.com." + ) + + +def test__get_universe_domain(): + client_universe_domain = "foo.com" + universe_domain_env = "bar.com" + + assert ( + ReservationBlocksClient._get_universe_domain( + client_universe_domain, universe_domain_env + ) + == client_universe_domain + ) + assert ( + ReservationBlocksClient._get_universe_domain(None, universe_domain_env) + == universe_domain_env + ) + assert ( + ReservationBlocksClient._get_universe_domain(None, None) + == ReservationBlocksClient._DEFAULT_UNIVERSE + ) + + with pytest.raises(ValueError) as excinfo: + ReservationBlocksClient._get_universe_domain("", None) + assert str(excinfo.value) == "Universe Domain cannot be an empty string." + + +@pytest.mark.parametrize( + "error_code,cred_info_json,show_cred_info", + [ + (401, CRED_INFO_JSON, True), + (403, CRED_INFO_JSON, True), + (404, CRED_INFO_JSON, True), + (500, CRED_INFO_JSON, False), + (401, None, False), + (403, None, False), + (404, None, False), + (500, None, False), + ], +) +def test__add_cred_info_for_auth_errors(error_code, cred_info_json, show_cred_info): + cred = mock.Mock(["get_cred_info"]) + cred.get_cred_info = mock.Mock(return_value=cred_info_json) + client = ReservationBlocksClient(credentials=cred) + client._transport._credentials = cred + + error = core_exceptions.GoogleAPICallError("message", details=["foo"]) + error.code = error_code + + client._add_cred_info_for_auth_errors(error) + if show_cred_info: + assert error.details == ["foo", CRED_INFO_STRING] + else: + assert error.details == ["foo"] + + +@pytest.mark.parametrize("error_code", [401, 403, 404, 500]) +def test__add_cred_info_for_auth_errors_no_get_cred_info(error_code): + cred = mock.Mock([]) + assert not hasattr(cred, "get_cred_info") + client = ReservationBlocksClient(credentials=cred) + client._transport._credentials = cred + + error = core_exceptions.GoogleAPICallError("message", details=[]) + error.code = error_code + + client._add_cred_info_for_auth_errors(error) + assert error.details == [] + + +@pytest.mark.parametrize( + "client_class,transport_name", + [ + (ReservationBlocksClient, "rest"), + ], +) +def test_reservation_blocks_client_from_service_account_info( + client_class, transport_name +): + creds = ga_credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_info" + ) as factory: + factory.return_value = creds + info = {"valid": True} + client = client_class.from_service_account_info(info, transport=transport_name) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == ( + "compute.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://compute.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_class,transport_name", + [ + (transports.ReservationBlocksRestTransport, "rest"), + ], +) +def test_reservation_blocks_client_service_account_always_use_jwt( + transport_class, transport_name +): + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + transport = transport_class(credentials=creds, always_use_jwt_access=True) + use_jwt.assert_called_once_with(True) + + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + transport = transport_class(credentials=creds, always_use_jwt_access=False) + use_jwt.assert_not_called() + + +@pytest.mark.parametrize( + "client_class,transport_name", + [ + (ReservationBlocksClient, "rest"), + ], +) +def test_reservation_blocks_client_from_service_account_file( + client_class, transport_name +): + creds = ga_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", transport=transport_name + ) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + client = client_class.from_service_account_json( + "dummy/file/path.json", transport=transport_name + ) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == ( + "compute.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://compute.googleapis.com" + ) + + +def test_reservation_blocks_client_get_transport_class(): + transport = ReservationBlocksClient.get_transport_class() + available_transports = [ + transports.ReservationBlocksRestTransport, + ] + assert transport in available_transports + + transport = ReservationBlocksClient.get_transport_class("rest") + assert transport == transports.ReservationBlocksRestTransport + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (ReservationBlocksClient, transports.ReservationBlocksRestTransport, "rest"), + ], +) +@mock.patch.object( + ReservationBlocksClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(ReservationBlocksClient), +) +def test_reservation_blocks_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(ReservationBlocksClient, "get_transport_class") as gtc: + transport = transport_class(credentials=ga_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(ReservationBlocksClient, "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(transport=transport_name, client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is + # "never". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is + # "always". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_MTLS_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + # Check the case quota_project_id is provided + options = client_options.ClientOptions(quota_project_id="octopus") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + # Check the case api_endpoint is provided + options = client_options.ClientOptions( + api_audience="https://language.googleapis.com" + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience="https://language.googleapis.com", + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,use_client_cert_env", + [ + ( + ReservationBlocksClient, + transports.ReservationBlocksRestTransport, + "rest", + "true", + ), + ( + ReservationBlocksClient, + transports.ReservationBlocksRestTransport, + "rest", + "false", + ), + ], +) +@mock.patch.object( + ReservationBlocksClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(ReservationBlocksClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_reservation_blocks_client_mtls_env_auto( + client_class, transport_class, transport_name, use_client_cert_env +): + # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default + # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists. + + # Check the case client_cert_source is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + options = client_options.ClientOptions( + client_cert_source=client_cert_source_callback + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + + if use_client_cert_env == "false": + expected_client_cert_source = None + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) + else: + expected_client_cert_source = client_cert_source_callback + expected_host = client.DEFAULT_MTLS_ENDPOINT + + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case ADC client cert is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=client_cert_source_callback, + ): + if use_client_cert_env == "false": + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) + expected_client_cert_source = None + else: + expected_host = client.DEFAULT_MTLS_ENDPOINT + expected_client_cert_source = client_cert_source_callback + + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case client_cert_source and ADC client cert are not provided. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize("client_class", [ReservationBlocksClient]) +@mock.patch.object( + ReservationBlocksClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(ReservationBlocksClient), +) +def test_reservation_blocks_client_get_mtls_endpoint_and_cert_source(client_class): + mock_client_cert_source = mock.Mock() + + # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "true". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + mock_api_endpoint = "foo" + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=mock_api_endpoint + ) + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source( + options + ) + assert api_endpoint == mock_api_endpoint + assert cert_source == mock_client_cert_source + + # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "false". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + mock_client_cert_source = mock.Mock() + mock_api_endpoint = "foo" + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=mock_api_endpoint + ) + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source( + options + ) + assert api_endpoint == mock_api_endpoint + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "never". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "always". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "auto" and default cert doesn't exist. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "auto" and default cert exists. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=mock_client_cert_source, + ): + ( + api_endpoint, + cert_source, + ) = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + assert cert_source == mock_client_cert_source + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + +@pytest.mark.parametrize("client_class", [ReservationBlocksClient]) +@mock.patch.object( + ReservationBlocksClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(ReservationBlocksClient), +) +def test_reservation_blocks_client_client_api_endpoint(client_class): + mock_client_cert_source = client_cert_source_callback + api_override = "foo.com" + default_universe = ReservationBlocksClient._DEFAULT_UNIVERSE + default_endpoint = ReservationBlocksClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = ReservationBlocksClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + # If ClientOptions.api_endpoint is set and GOOGLE_API_USE_CLIENT_CERTIFICATE="true", + # use ClientOptions.api_endpoint as the api endpoint regardless. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.requests.AuthorizedSession.configure_mtls_channel" + ): + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=api_override + ) + client = client_class( + client_options=options, + credentials=ga_credentials.AnonymousCredentials(), + ) + assert client.api_endpoint == api_override + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == default_endpoint + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="always", + # use the DEFAULT_MTLS_ENDPOINT as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + + # If ClientOptions.api_endpoint is not set, GOOGLE_API_USE_MTLS_ENDPOINT="auto" (default), + # GOOGLE_API_USE_CLIENT_CERTIFICATE="false" (default), default cert source doesn't exist, + # and ClientOptions.universe_domain="bar.com", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with universe domain as the api endpoint. + options = client_options.ClientOptions() + universe_exists = hasattr(options, "universe_domain") + if universe_exists: + options = client_options.ClientOptions(universe_domain=mock_universe) + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + else: + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == ( + mock_endpoint if universe_exists else default_endpoint + ) + assert client.universe_domain == ( + mock_universe if universe_exists else default_universe + ) + + # If ClientOptions does not have a universe domain attribute and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + options = client_options.ClientOptions() + if hasattr(options, "universe_domain"): + delattr(options, "universe_domain") + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == default_endpoint + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (ReservationBlocksClient, transports.ReservationBlocksRestTransport, "rest"), + ], +) +def test_reservation_blocks_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, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=["1", "2"], + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,grpc_helpers", + [ + ( + ReservationBlocksClient, + transports.ReservationBlocksRestTransport, + "rest", + None, + ), + ], +) +def test_reservation_blocks_client_client_options_credentials_file( + client_class, transport_class, transport_name, grpc_helpers +): + # 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, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file="credentials.json", + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +def test_get_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.get] = mock_rpc + + request = {} + client.get(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_get_rest_required_fields(request_type=compute.GetReservationBlockRequest): + transport_class = transports.ReservationBlocksRestTransport + + request_init = {} + request_init["project"] = "" + request_init["reservation"] = "" + request_init["reservation_block"] = "" + request_init["zone"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["project"] = "project_value" + jsonified_request["reservation"] = "reservation_value" + jsonified_request["reservationBlock"] = "reservation_block_value" + jsonified_request["zone"] = "zone_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "project" in jsonified_request + assert jsonified_request["project"] == "project_value" + assert "reservation" in jsonified_request + assert jsonified_request["reservation"] == "reservation_value" + assert "reservationBlock" in jsonified_request + assert jsonified_request["reservationBlock"] == "reservation_block_value" + assert "zone" in jsonified_request + assert jsonified_request["zone"] == "zone_value" + + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = compute.ReservationBlocksGetResponse() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = compute.ReservationBlocksGetResponse.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.get(request) + + expected_params = [] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_get_rest_unset_required_fields(): + transport = transports.ReservationBlocksRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.get._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "project", + "reservation", + "reservationBlock", + "zone", + ) + ) + ) + + +def test_get_rest_flattened(): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = compute.ReservationBlocksGetResponse() + + # get arguments that satisfy an http rule for this method + sample_request = { + "project": "sample1", + "zone": "sample2", + "reservation": "sample3", + "reservation_block": "sample4", + } + + # get truthy value for each flattened field + mock_args = dict( + project="project_value", + zone="zone_value", + reservation="reservation_value", + reservation_block="reservation_block_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = compute.ReservationBlocksGetResponse.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + client.get(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/compute/v1/projects/{project}/zones/{zone}/reservations/{reservation}/reservationBlocks/{reservation_block}" + % client.transport._host, + args[1], + ) + + +def test_get_rest_flattened_error(transport: str = "rest"): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get( + compute.GetReservationBlockRequest(), + project="project_value", + zone="zone_value", + reservation="reservation_value", + reservation_block="reservation_block_value", + ) + + +def test_list_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.list in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.list] = mock_rpc + + request = {} + client.list(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_list_rest_required_fields(request_type=compute.ListReservationBlocksRequest): + transport_class = transports.ReservationBlocksRestTransport + + request_init = {} + request_init["project"] = "" + request_init["reservation"] = "" + request_init["zone"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["project"] = "project_value" + jsonified_request["reservation"] = "reservation_value" + jsonified_request["zone"] = "zone_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set( + ( + "filter", + "max_results", + "order_by", + "page_token", + "return_partial_success", + ) + ) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "project" in jsonified_request + assert jsonified_request["project"] == "project_value" + assert "reservation" in jsonified_request + assert jsonified_request["reservation"] == "reservation_value" + assert "zone" in jsonified_request + assert jsonified_request["zone"] == "zone_value" + + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = compute.ReservationBlocksListResponse() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = compute.ReservationBlocksListResponse.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.list(request) + + expected_params = [] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_list_rest_unset_required_fields(): + transport = transports.ReservationBlocksRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.list._get_unset_required_fields({}) + assert set(unset_fields) == ( + set( + ( + "filter", + "maxResults", + "orderBy", + "pageToken", + "returnPartialSuccess", + ) + ) + & set( + ( + "project", + "reservation", + "zone", + ) + ) + ) + + +def test_list_rest_flattened(): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = compute.ReservationBlocksListResponse() + + # get arguments that satisfy an http rule for this method + sample_request = { + "project": "sample1", + "zone": "sample2", + "reservation": "sample3", + } + + # get truthy value for each flattened field + mock_args = dict( + project="project_value", + zone="zone_value", + reservation="reservation_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = compute.ReservationBlocksListResponse.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + client.list(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/compute/v1/projects/{project}/zones/{zone}/reservations/{reservation}/reservationBlocks" + % client.transport._host, + args[1], + ) + + +def test_list_rest_flattened_error(transport: str = "rest"): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list( + compute.ListReservationBlocksRequest(), + project="project_value", + zone="zone_value", + reservation="reservation_value", + ) + + +def test_list_rest_pager(transport: str = "rest"): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # TODO(kbandes): remove this mock unless there's a good reason for it. + # with mock.patch.object(path_template, 'transcode') as transcode: + # Set the response as a series of pages + response = ( + compute.ReservationBlocksListResponse( + items=[ + compute.ReservationBlock(), + compute.ReservationBlock(), + compute.ReservationBlock(), + ], + next_page_token="abc", + ), + compute.ReservationBlocksListResponse( + items=[], + next_page_token="def", + ), + compute.ReservationBlocksListResponse( + items=[ + compute.ReservationBlock(), + ], + next_page_token="ghi", + ), + compute.ReservationBlocksListResponse( + items=[ + compute.ReservationBlock(), + compute.ReservationBlock(), + ], + ), + ) + # Two responses for two calls + response = response + response + + # Wrap the values into proper Response objs + response = tuple( + compute.ReservationBlocksListResponse.to_json(x) for x in response + ) + return_values = tuple(Response() for i in response) + for return_val, response_val in zip(return_values, response): + return_val._content = response_val.encode("UTF-8") + return_val.status_code = 200 + req.side_effect = return_values + + sample_request = { + "project": "sample1", + "zone": "sample2", + "reservation": "sample3", + } + + pager = client.list(request=sample_request) + + results = list(pager) + assert len(results) == 6 + assert all(isinstance(i, compute.ReservationBlock) for i in results) + + pages = list(client.list(request=sample_request).pages) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +def test_perform_maintenance_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.perform_maintenance in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.perform_maintenance + ] = mock_rpc + + request = {} + client.perform_maintenance(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.perform_maintenance(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_perform_maintenance_rest_required_fields( + request_type=compute.PerformMaintenanceReservationBlockRequest, +): + transport_class = transports.ReservationBlocksRestTransport + + request_init = {} + request_init["project"] = "" + request_init["reservation"] = "" + request_init["reservation_block"] = "" + request_init["zone"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).perform_maintenance._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["project"] = "project_value" + jsonified_request["reservation"] = "reservation_value" + jsonified_request["reservationBlock"] = "reservation_block_value" + jsonified_request["zone"] = "zone_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).perform_maintenance._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("request_id",)) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "project" in jsonified_request + assert jsonified_request["project"] == "project_value" + assert "reservation" in jsonified_request + assert jsonified_request["reservation"] == "reservation_value" + assert "reservationBlock" in jsonified_request + assert jsonified_request["reservationBlock"] == "reservation_block_value" + assert "zone" in jsonified_request + assert jsonified_request["zone"] == "zone_value" + + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = compute.Operation() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = compute.Operation.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.perform_maintenance(request) + + expected_params = [] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_perform_maintenance_rest_unset_required_fields(): + transport = transports.ReservationBlocksRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.perform_maintenance._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(("requestId",)) + & set( + ( + "project", + "reservation", + "reservationBlock", + "reservationsBlocksPerformMaintenanceRequestResource", + "zone", + ) + ) + ) + + +def test_perform_maintenance_rest_flattened(): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = compute.Operation() + + # get arguments that satisfy an http rule for this method + sample_request = { + "project": "sample1", + "zone": "sample2", + "reservation": "sample3", + "reservation_block": "sample4", + } + + # get truthy value for each flattened field + mock_args = dict( + project="project_value", + zone="zone_value", + reservation="reservation_value", + reservation_block="reservation_block_value", + reservations_blocks_perform_maintenance_request_resource=compute.ReservationsBlocksPerformMaintenanceRequest( + maintenance_scope="maintenance_scope_value" + ), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = compute.Operation.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + client.perform_maintenance(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/compute/v1/projects/{project}/zones/{zone}/reservations/{reservation}/reservationBlocks/{reservation_block}/performMaintenance" + % client.transport._host, + args[1], + ) + + +def test_perform_maintenance_rest_flattened_error(transport: str = "rest"): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.perform_maintenance( + compute.PerformMaintenanceReservationBlockRequest(), + project="project_value", + zone="zone_value", + reservation="reservation_value", + reservation_block="reservation_block_value", + reservations_blocks_perform_maintenance_request_resource=compute.ReservationsBlocksPerformMaintenanceRequest( + maintenance_scope="maintenance_scope_value" + ), + ) + + +def test_perform_maintenance_unary_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.perform_maintenance in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.perform_maintenance + ] = mock_rpc + + request = {} + client.perform_maintenance_unary(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.perform_maintenance_unary(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_perform_maintenance_unary_rest_required_fields( + request_type=compute.PerformMaintenanceReservationBlockRequest, +): + transport_class = transports.ReservationBlocksRestTransport + + request_init = {} + request_init["project"] = "" + request_init["reservation"] = "" + request_init["reservation_block"] = "" + request_init["zone"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).perform_maintenance._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["project"] = "project_value" + jsonified_request["reservation"] = "reservation_value" + jsonified_request["reservationBlock"] = "reservation_block_value" + jsonified_request["zone"] = "zone_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).perform_maintenance._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("request_id",)) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "project" in jsonified_request + assert jsonified_request["project"] == "project_value" + assert "reservation" in jsonified_request + assert jsonified_request["reservation"] == "reservation_value" + assert "reservationBlock" in jsonified_request + assert jsonified_request["reservationBlock"] == "reservation_block_value" + assert "zone" in jsonified_request + assert jsonified_request["zone"] == "zone_value" + + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = compute.Operation() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = compute.Operation.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.perform_maintenance_unary(request) + + expected_params = [] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_perform_maintenance_unary_rest_unset_required_fields(): + transport = transports.ReservationBlocksRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.perform_maintenance._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(("requestId",)) + & set( + ( + "project", + "reservation", + "reservationBlock", + "reservationsBlocksPerformMaintenanceRequestResource", + "zone", + ) + ) + ) + + +def test_perform_maintenance_unary_rest_flattened(): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = compute.Operation() + + # get arguments that satisfy an http rule for this method + sample_request = { + "project": "sample1", + "zone": "sample2", + "reservation": "sample3", + "reservation_block": "sample4", + } + + # get truthy value for each flattened field + mock_args = dict( + project="project_value", + zone="zone_value", + reservation="reservation_value", + reservation_block="reservation_block_value", + reservations_blocks_perform_maintenance_request_resource=compute.ReservationsBlocksPerformMaintenanceRequest( + maintenance_scope="maintenance_scope_value" + ), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = compute.Operation.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + client.perform_maintenance_unary(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/compute/v1/projects/{project}/zones/{zone}/reservations/{reservation}/reservationBlocks/{reservation_block}/performMaintenance" + % client.transport._host, + args[1], + ) + + +def test_perform_maintenance_unary_rest_flattened_error(transport: str = "rest"): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.perform_maintenance_unary( + compute.PerformMaintenanceReservationBlockRequest(), + project="project_value", + zone="zone_value", + reservation="reservation_value", + reservation_block="reservation_block_value", + reservations_blocks_perform_maintenance_request_resource=compute.ReservationsBlocksPerformMaintenanceRequest( + maintenance_scope="maintenance_scope_value" + ), + ) + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.ReservationBlocksRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.ReservationBlocksRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = ReservationBlocksClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide an api_key and a transport instance. + transport = transports.ReservationBlocksRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = ReservationBlocksClient( + client_options=options, + transport=transport, + ) + + # It is an error to provide an api_key and a credential. + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = ReservationBlocksClient( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.ReservationBlocksRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = ReservationBlocksClient( + client_options={"scopes": ["1", "2"]}, + transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.ReservationBlocksRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + client = ReservationBlocksClient(transport=transport) + assert client.transport is transport + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.ReservationBlocksRestTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + +def test_transport_kind_rest(): + transport = ReservationBlocksClient.get_transport_class("rest")( + credentials=ga_credentials.AnonymousCredentials() + ) + assert transport.kind == "rest" + + +def test_get_rest_bad_request(request_type=compute.GetReservationBlockRequest): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + # send a request that will satisfy transcoding + request_init = { + "project": "sample1", + "zone": "sample2", + "reservation": "sample3", + "reservation_block": "sample4", + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = mock.Mock() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.get(request) + + +@pytest.mark.parametrize( + "request_type", + [ + compute.GetReservationBlockRequest, + dict, + ], +) +def test_get_rest_call_success(request_type): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + # send a request that will satisfy transcoding + request_init = { + "project": "sample1", + "zone": "sample2", + "reservation": "sample3", + "reservation_block": "sample4", + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = compute.ReservationBlocksGetResponse() + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = compute.ReservationBlocksGetResponse.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value.content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = client.get(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, compute.ReservationBlocksGetResponse) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_get_rest_interceptors(null_interceptor): + transport = transports.ReservationBlocksRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ReservationBlocksRestInterceptor(), + ) + client = ReservationBlocksClient(transport=transport) + + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.ReservationBlocksRestInterceptor, "post_get" + ) as post, mock.patch.object( + transports.ReservationBlocksRestInterceptor, "post_get_with_metadata" + ) as post_with_metadata, mock.patch.object( + transports.ReservationBlocksRestInterceptor, "pre_get" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = compute.GetReservationBlockRequest.pb( + compute.GetReservationBlockRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = compute.ReservationBlocksGetResponse.to_json( + compute.ReservationBlocksGetResponse() + ) + req.return_value.content = return_value + + request = compute.GetReservationBlockRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = compute.ReservationBlocksGetResponse() + post_with_metadata.return_value = ( + compute.ReservationBlocksGetResponse(), + metadata, + ) + + client.get( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + +def test_list_rest_bad_request(request_type=compute.ListReservationBlocksRequest): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + # send a request that will satisfy transcoding + request_init = {"project": "sample1", "zone": "sample2", "reservation": "sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = mock.Mock() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.list(request) + + +@pytest.mark.parametrize( + "request_type", + [ + compute.ListReservationBlocksRequest, + dict, + ], +) +def test_list_rest_call_success(request_type): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + # send a request that will satisfy transcoding + request_init = {"project": "sample1", "zone": "sample2", "reservation": "sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = compute.ReservationBlocksListResponse( + id="id_value", + kind="kind_value", + next_page_token="next_page_token_value", + self_link="self_link_value", + ) + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = compute.ReservationBlocksListResponse.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value.content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = client.list(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListPager) + assert response.id == "id_value" + assert response.kind == "kind_value" + assert response.next_page_token == "next_page_token_value" + assert response.self_link == "self_link_value" + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_list_rest_interceptors(null_interceptor): + transport = transports.ReservationBlocksRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ReservationBlocksRestInterceptor(), + ) + client = ReservationBlocksClient(transport=transport) + + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.ReservationBlocksRestInterceptor, "post_list" + ) as post, mock.patch.object( + transports.ReservationBlocksRestInterceptor, "post_list_with_metadata" + ) as post_with_metadata, mock.patch.object( + transports.ReservationBlocksRestInterceptor, "pre_list" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = compute.ListReservationBlocksRequest.pb( + compute.ListReservationBlocksRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = compute.ReservationBlocksListResponse.to_json( + compute.ReservationBlocksListResponse() + ) + req.return_value.content = return_value + + request = compute.ListReservationBlocksRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = compute.ReservationBlocksListResponse() + post_with_metadata.return_value = ( + compute.ReservationBlocksListResponse(), + metadata, + ) + + client.list( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + +def test_perform_maintenance_rest_bad_request( + request_type=compute.PerformMaintenanceReservationBlockRequest, +): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + # send a request that will satisfy transcoding + request_init = { + "project": "sample1", + "zone": "sample2", + "reservation": "sample3", + "reservation_block": "sample4", + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = mock.Mock() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.perform_maintenance(request) + + +@pytest.mark.parametrize( + "request_type", + [ + compute.PerformMaintenanceReservationBlockRequest, + dict, + ], +) +def test_perform_maintenance_rest_call_success(request_type): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + # send a request that will satisfy transcoding + request_init = { + "project": "sample1", + "zone": "sample2", + "reservation": "sample3", + "reservation_block": "sample4", + } + request_init["reservations_blocks_perform_maintenance_request_resource"] = { + "maintenance_scope": "maintenance_scope_value" + } + # The version of a generated dependency at test runtime may differ from the version used during generation. + # Delete any fields which are not present in the current runtime dependency + # See https://github.com/googleapis/gapic-generator-python/issues/1748 + + # Determine if the message type is proto-plus or protobuf + test_field = compute.PerformMaintenanceReservationBlockRequest.meta.fields[ + "reservations_blocks_perform_maintenance_request_resource" + ] + + def get_message_fields(field): + # Given a field which is a message (composite type), return a list with + # all the fields of the message. + # If the field is not a composite type, return an empty list. + message_fields = [] + + if hasattr(field, "message") and field.message: + is_field_type_proto_plus_type = not hasattr(field.message, "DESCRIPTOR") + + if is_field_type_proto_plus_type: + message_fields = field.message.meta.fields.values() + # Add `# pragma: NO COVER` because there may not be any `*_pb2` field types + else: # pragma: NO COVER + message_fields = field.message.DESCRIPTOR.fields + return message_fields + + runtime_nested_fields = [ + (field.name, nested_field.name) + for field in get_message_fields(test_field) + for nested_field in get_message_fields(field) + ] + + subfields_not_in_runtime = [] + + # For each item in the sample request, create a list of sub fields which are not present at runtime + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for field, value in request_init[ + "reservations_blocks_perform_maintenance_request_resource" + ].items(): # pragma: NO COVER + result = None + is_repeated = False + # For repeated fields + if isinstance(value, list) and len(value): + is_repeated = True + result = value[0] + # For fields where the type is another message + if isinstance(value, dict): + result = value + + if result and hasattr(result, "keys"): + for subfield in result.keys(): + if (field, subfield) not in runtime_nested_fields: + subfields_not_in_runtime.append( + { + "field": field, + "subfield": subfield, + "is_repeated": is_repeated, + } + ) + + # Remove fields from the sample request which are not present in the runtime version of the dependency + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for subfield_to_delete in subfields_not_in_runtime: # pragma: NO COVER + field = subfield_to_delete.get("field") + field_repeated = subfield_to_delete.get("is_repeated") + subfield = subfield_to_delete.get("subfield") + if subfield: + if field_repeated: + for i in range( + 0, + len( + request_init[ + "reservations_blocks_perform_maintenance_request_resource" + ][field] + ), + ): + del request_init[ + "reservations_blocks_perform_maintenance_request_resource" + ][field][i][subfield] + else: + del request_init[ + "reservations_blocks_perform_maintenance_request_resource" + ][field][subfield] + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = compute.Operation( + client_operation_id="client_operation_id_value", + creation_timestamp="creation_timestamp_value", + description="description_value", + end_time="end_time_value", + http_error_message="http_error_message_value", + http_error_status_code=2374, + id=205, + insert_time="insert_time_value", + kind="kind_value", + name="name_value", + operation_group_id="operation_group_id_value", + operation_type="operation_type_value", + progress=885, + region="region_value", + self_link="self_link_value", + start_time="start_time_value", + status=compute.Operation.Status.DONE, + status_message="status_message_value", + target_id=947, + target_link="target_link_value", + user="user_value", + zone="zone_value", + ) + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = compute.Operation.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value.content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = client.perform_maintenance(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, extended_operation.ExtendedOperation) + assert response.client_operation_id == "client_operation_id_value" + assert response.creation_timestamp == "creation_timestamp_value" + assert response.description == "description_value" + assert response.end_time == "end_time_value" + assert response.http_error_message == "http_error_message_value" + assert response.http_error_status_code == 2374 + assert response.id == 205 + assert response.insert_time == "insert_time_value" + assert response.kind == "kind_value" + assert response.name == "name_value" + assert response.operation_group_id == "operation_group_id_value" + assert response.operation_type == "operation_type_value" + assert response.progress == 885 + assert response.region == "region_value" + assert response.self_link == "self_link_value" + assert response.start_time == "start_time_value" + assert response.status == compute.Operation.Status.DONE + assert response.status_message == "status_message_value" + assert response.target_id == 947 + assert response.target_link == "target_link_value" + assert response.user == "user_value" + assert response.zone == "zone_value" + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_perform_maintenance_rest_interceptors(null_interceptor): + transport = transports.ReservationBlocksRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ReservationBlocksRestInterceptor(), + ) + client = ReservationBlocksClient(transport=transport) + + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.ReservationBlocksRestInterceptor, "post_perform_maintenance" + ) as post, mock.patch.object( + transports.ReservationBlocksRestInterceptor, + "post_perform_maintenance_with_metadata", + ) as post_with_metadata, mock.patch.object( + transports.ReservationBlocksRestInterceptor, "pre_perform_maintenance" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = compute.PerformMaintenanceReservationBlockRequest.pb( + compute.PerformMaintenanceReservationBlockRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = compute.Operation.to_json(compute.Operation()) + req.return_value.content = return_value + + request = compute.PerformMaintenanceReservationBlockRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = compute.Operation() + post_with_metadata.return_value = compute.Operation(), metadata + + client.perform_maintenance( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + +def test_initialize_client_w_rest(): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + assert client is not None + + +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_get_empty_call_rest(): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.get), "__call__") as call: + client.get(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = compute.GetReservationBlockRequest() + + assert args[0] == request_msg + + +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_list_empty_call_rest(): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.list), "__call__") as call: + client.list(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = compute.ListReservationBlocksRequest() + + assert args[0] == request_msg + + +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_perform_maintenance_unary_empty_call_rest(): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.perform_maintenance), "__call__" + ) as call: + client.perform_maintenance_unary(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = compute.PerformMaintenanceReservationBlockRequest() + + assert args[0] == request_msg + + +def test_reservation_blocks_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(core_exceptions.DuplicateCredentialArgs): + transport = transports.ReservationBlocksTransport( + credentials=ga_credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_reservation_blocks_base_transport(): + # Instantiate the base transport. + with mock.patch( + "google.cloud.compute_v1.services.reservation_blocks.transports.ReservationBlocksTransport.__init__" + ) as Transport: + Transport.return_value = None + transport = transports.ReservationBlocksTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ( + "get", + "list", + "perform_maintenance", + ) + for method in methods: + with pytest.raises(NotImplementedError): + getattr(transport, method)(request=object()) + + with pytest.raises(NotImplementedError): + transport.close() + + # Catch all for all remaining methods and properties + remainder = [ + "kind", + ] + for r in remainder: + with pytest.raises(NotImplementedError): + getattr(transport, r)() + + +def test_reservation_blocks_base_transport_with_credentials_file(): + # Instantiate the base transport with a credentials file + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch( + "google.cloud.compute_v1.services.reservation_blocks.transports.ReservationBlocksTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.ReservationBlocksTransport( + credentials_file="credentials.json", + quota_project_id="octopus", + ) + load_creds.assert_called_once_with( + "credentials.json", + scopes=None, + default_scopes=( + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/cloud-platform", + ), + quota_project_id="octopus", + ) + + +def test_reservation_blocks_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( + "google.cloud.compute_v1.services.reservation_blocks.transports.ReservationBlocksTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.ReservationBlocksTransport() + adc.assert_called_once() + + +def test_reservation_blocks_auth_adc(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + ReservationBlocksClient() + adc.assert_called_once_with( + scopes=None, + default_scopes=( + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/cloud-platform", + ), + quota_project_id=None, + ) + + +def test_reservation_blocks_http_transport_client_cert_source_for_mtls(): + cred = ga_credentials.AnonymousCredentials() + with mock.patch( + "google.auth.transport.requests.AuthorizedSession.configure_mtls_channel" + ) as mock_configure_mtls_channel: + transports.ReservationBlocksRestTransport( + credentials=cred, client_cert_source_for_mtls=client_cert_source_callback + ) + mock_configure_mtls_channel.assert_called_once_with(client_cert_source_callback) + + +@pytest.mark.parametrize( + "transport_name", + [ + "rest", + ], +) +def test_reservation_blocks_host_no_port(transport_name): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="compute.googleapis.com" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "compute.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://compute.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "rest", + ], +) +def test_reservation_blocks_host_with_port(transport_name): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="compute.googleapis.com:8000" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "compute.googleapis.com:8000" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://compute.googleapis.com:8000" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "rest", + ], +) +def test_reservation_blocks_client_transport_session_collision(transport_name): + creds1 = ga_credentials.AnonymousCredentials() + creds2 = ga_credentials.AnonymousCredentials() + client1 = ReservationBlocksClient( + credentials=creds1, + transport=transport_name, + ) + client2 = ReservationBlocksClient( + credentials=creds2, + transport=transport_name, + ) + session1 = client1.transport.get._session + session2 = client2.transport.get._session + assert session1 != session2 + session1 = client1.transport.list._session + session2 = client2.transport.list._session + assert session1 != session2 + session1 = client1.transport.perform_maintenance._session + session2 = client2.transport.perform_maintenance._session + assert session1 != session2 + + +def test_common_billing_account_path(): + billing_account = "squid" + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = ReservationBlocksClient.common_billing_account_path(billing_account) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "clam", + } + path = ReservationBlocksClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = ReservationBlocksClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "whelk" + expected = "folders/{folder}".format( + folder=folder, + ) + actual = ReservationBlocksClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "octopus", + } + path = ReservationBlocksClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = ReservationBlocksClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "oyster" + expected = "organizations/{organization}".format( + organization=organization, + ) + actual = ReservationBlocksClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "nudibranch", + } + path = ReservationBlocksClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = ReservationBlocksClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "cuttlefish" + expected = "projects/{project}".format( + project=project, + ) + actual = ReservationBlocksClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "mussel", + } + path = ReservationBlocksClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = ReservationBlocksClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "winkle" + location = "nautilus" + expected = "projects/{project}/locations/{location}".format( + project=project, + location=location, + ) + actual = ReservationBlocksClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "scallop", + "location": "abalone", + } + path = ReservationBlocksClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = ReservationBlocksClient.parse_common_location_path(path) + assert expected == actual + + +def test_client_with_default_client_info(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object( + transports.ReservationBlocksTransport, "_prep_wrapped_messages" + ) as prep: + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.ReservationBlocksTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = ReservationBlocksClient.get_transport_class() + transport = transport_class( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + +def test_transport_close_rest(): + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + with mock.patch.object( + type(getattr(client.transport, "_session")), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "rest", + ] + for transport in transports: + client = ReservationBlocksClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() + + +@pytest.mark.parametrize( + "client_class,transport_class", + [ + (ReservationBlocksClient, transports.ReservationBlocksRestTransport), + ], +) +def test_api_key_credentials(client_class, transport_class): + with mock.patch.object( + google.auth._default, "get_api_key_credentials", create=True + ) as get_api_key_credentials: + mock_cred = mock.Mock() + get_api_key_credentials.return_value = mock_cred + options = client_options.ClientOptions() + options.api_key = "api_key" + 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=mock_cred, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) diff --git a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_reservations.py b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_reservations.py index 45727925ad09..c773cdbb0e4d 100644 --- a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_reservations.py +++ b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_reservations.py @@ -2744,6 +2744,448 @@ def test_list_rest_pager(transport: str = "rest"): assert page_.raw_page.next_page_token == token +def test_perform_maintenance_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = ReservationsClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.perform_maintenance in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.perform_maintenance + ] = mock_rpc + + request = {} + client.perform_maintenance(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.perform_maintenance(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_perform_maintenance_rest_required_fields( + request_type=compute.PerformMaintenanceReservationRequest, +): + transport_class = transports.ReservationsRestTransport + + request_init = {} + request_init["project"] = "" + request_init["reservation"] = "" + request_init["zone"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).perform_maintenance._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["project"] = "project_value" + jsonified_request["reservation"] = "reservation_value" + jsonified_request["zone"] = "zone_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).perform_maintenance._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("request_id",)) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "project" in jsonified_request + assert jsonified_request["project"] == "project_value" + assert "reservation" in jsonified_request + assert jsonified_request["reservation"] == "reservation_value" + assert "zone" in jsonified_request + assert jsonified_request["zone"] == "zone_value" + + client = ReservationsClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = compute.Operation() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = compute.Operation.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.perform_maintenance(request) + + expected_params = [] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_perform_maintenance_rest_unset_required_fields(): + transport = transports.ReservationsRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.perform_maintenance._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(("requestId",)) + & set( + ( + "project", + "reservation", + "reservationsPerformMaintenanceRequestResource", + "zone", + ) + ) + ) + + +def test_perform_maintenance_rest_flattened(): + client = ReservationsClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = compute.Operation() + + # get arguments that satisfy an http rule for this method + sample_request = { + "project": "sample1", + "zone": "sample2", + "reservation": "sample3", + } + + # get truthy value for each flattened field + mock_args = dict( + project="project_value", + zone="zone_value", + reservation="reservation_value", + reservations_perform_maintenance_request_resource=compute.ReservationsPerformMaintenanceRequest( + maintenance_scope="maintenance_scope_value" + ), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = compute.Operation.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + client.perform_maintenance(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/compute/v1/projects/{project}/zones/{zone}/reservations/{reservation}/performMaintenance" + % client.transport._host, + args[1], + ) + + +def test_perform_maintenance_rest_flattened_error(transport: str = "rest"): + client = ReservationsClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.perform_maintenance( + compute.PerformMaintenanceReservationRequest(), + project="project_value", + zone="zone_value", + reservation="reservation_value", + reservations_perform_maintenance_request_resource=compute.ReservationsPerformMaintenanceRequest( + maintenance_scope="maintenance_scope_value" + ), + ) + + +def test_perform_maintenance_unary_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = ReservationsClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.perform_maintenance in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.perform_maintenance + ] = mock_rpc + + request = {} + client.perform_maintenance_unary(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.perform_maintenance_unary(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_perform_maintenance_unary_rest_required_fields( + request_type=compute.PerformMaintenanceReservationRequest, +): + transport_class = transports.ReservationsRestTransport + + request_init = {} + request_init["project"] = "" + request_init["reservation"] = "" + request_init["zone"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).perform_maintenance._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["project"] = "project_value" + jsonified_request["reservation"] = "reservation_value" + jsonified_request["zone"] = "zone_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).perform_maintenance._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("request_id",)) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "project" in jsonified_request + assert jsonified_request["project"] == "project_value" + assert "reservation" in jsonified_request + assert jsonified_request["reservation"] == "reservation_value" + assert "zone" in jsonified_request + assert jsonified_request["zone"] == "zone_value" + + client = ReservationsClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = compute.Operation() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = compute.Operation.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.perform_maintenance_unary(request) + + expected_params = [] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_perform_maintenance_unary_rest_unset_required_fields(): + transport = transports.ReservationsRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.perform_maintenance._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(("requestId",)) + & set( + ( + "project", + "reservation", + "reservationsPerformMaintenanceRequestResource", + "zone", + ) + ) + ) + + +def test_perform_maintenance_unary_rest_flattened(): + client = ReservationsClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = compute.Operation() + + # get arguments that satisfy an http rule for this method + sample_request = { + "project": "sample1", + "zone": "sample2", + "reservation": "sample3", + } + + # get truthy value for each flattened field + mock_args = dict( + project="project_value", + zone="zone_value", + reservation="reservation_value", + reservations_perform_maintenance_request_resource=compute.ReservationsPerformMaintenanceRequest( + maintenance_scope="maintenance_scope_value" + ), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = compute.Operation.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + client.perform_maintenance_unary(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/compute/v1/projects/{project}/zones/{zone}/reservations/{reservation}/performMaintenance" + % client.transport._host, + args[1], + ) + + +def test_perform_maintenance_unary_rest_flattened_error(transport: str = "rest"): + client = ReservationsClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.perform_maintenance_unary( + compute.PerformMaintenanceReservationRequest(), + project="project_value", + zone="zone_value", + reservation="reservation_value", + reservations_perform_maintenance_request_resource=compute.ReservationsPerformMaintenanceRequest( + maintenance_scope="maintenance_scope_value" + ), + ) + + def test_resize_rest_use_cached_wrapped_rpc(): # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, # instead of constructing them on each call @@ -4521,9 +4963,11 @@ def test_get_rest_call_success(request_type): return_value = compute.Reservation( commitment="commitment_value", creation_timestamp="creation_timestamp_value", + deployment_type="deployment_type_value", description="description_value", id=205, kind="kind_value", + linked_commitments=["linked_commitments_value"], name="name_value", satisfies_pzs=True, self_link="self_link_value", @@ -4548,9 +4992,11 @@ def test_get_rest_call_success(request_type): assert isinstance(response, compute.Reservation) assert response.commitment == "commitment_value" assert response.creation_timestamp == "creation_timestamp_value" + assert response.deployment_type == "deployment_type_value" assert response.description == "description_value" assert response.id == 205 assert response.kind == "kind_value" + assert response.linked_commitments == ["linked_commitments_value"] assert response.name == "name_value" assert response.satisfies_pzs is True assert response.self_link == "self_link_value" @@ -4803,19 +5249,38 @@ def test_insert_rest_call_success(request_type): }, "commitment": "commitment_value", "creation_timestamp": "creation_timestamp_value", + "deployment_type": "deployment_type_value", "description": "description_value", "id": 205, "kind": "kind_value", + "linked_commitments": [ + "linked_commitments_value1", + "linked_commitments_value2", + ], "name": "name_value", "reservation_sharing_policy": { "service_share_type": "service_share_type_value" }, "resource_policies": {}, "resource_status": { + "reservation_block_count": 2468, + "reservation_maintenance": { + "maintenance_ongoing_count": 2651, + "maintenance_pending_count": 2639, + "scheduling_type": "scheduling_type_value", + "upcoming_group_maintenance": { + "can_reschedule": True, + "latest_window_start_time": "latest_window_start_time_value", + "maintenance_status": "maintenance_status_value", + "type_": "type__value", + "window_end_time": "window_end_time_value", + "window_start_time": "window_start_time_value", + }, + }, "specific_sku_allocation": { "source_instance_template_id": "source_instance_template_id_value", "utilizations": {}, - } + }, }, "satisfies_pzs": True, "self_link": "self_link_value", @@ -5172,6 +5637,260 @@ def test_list_rest_interceptors(null_interceptor): post_with_metadata.assert_called_once() +def test_perform_maintenance_rest_bad_request( + request_type=compute.PerformMaintenanceReservationRequest, +): + client = ReservationsClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + # send a request that will satisfy transcoding + request_init = {"project": "sample1", "zone": "sample2", "reservation": "sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = mock.Mock() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.perform_maintenance(request) + + +@pytest.mark.parametrize( + "request_type", + [ + compute.PerformMaintenanceReservationRequest, + dict, + ], +) +def test_perform_maintenance_rest_call_success(request_type): + client = ReservationsClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + # send a request that will satisfy transcoding + request_init = {"project": "sample1", "zone": "sample2", "reservation": "sample3"} + request_init["reservations_perform_maintenance_request_resource"] = { + "maintenance_scope": "maintenance_scope_value" + } + # The version of a generated dependency at test runtime may differ from the version used during generation. + # Delete any fields which are not present in the current runtime dependency + # See https://github.com/googleapis/gapic-generator-python/issues/1748 + + # Determine if the message type is proto-plus or protobuf + test_field = compute.PerformMaintenanceReservationRequest.meta.fields[ + "reservations_perform_maintenance_request_resource" + ] + + def get_message_fields(field): + # Given a field which is a message (composite type), return a list with + # all the fields of the message. + # If the field is not a composite type, return an empty list. + message_fields = [] + + if hasattr(field, "message") and field.message: + is_field_type_proto_plus_type = not hasattr(field.message, "DESCRIPTOR") + + if is_field_type_proto_plus_type: + message_fields = field.message.meta.fields.values() + # Add `# pragma: NO COVER` because there may not be any `*_pb2` field types + else: # pragma: NO COVER + message_fields = field.message.DESCRIPTOR.fields + return message_fields + + runtime_nested_fields = [ + (field.name, nested_field.name) + for field in get_message_fields(test_field) + for nested_field in get_message_fields(field) + ] + + subfields_not_in_runtime = [] + + # For each item in the sample request, create a list of sub fields which are not present at runtime + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for field, value in request_init[ + "reservations_perform_maintenance_request_resource" + ].items(): # pragma: NO COVER + result = None + is_repeated = False + # For repeated fields + if isinstance(value, list) and len(value): + is_repeated = True + result = value[0] + # For fields where the type is another message + if isinstance(value, dict): + result = value + + if result and hasattr(result, "keys"): + for subfield in result.keys(): + if (field, subfield) not in runtime_nested_fields: + subfields_not_in_runtime.append( + { + "field": field, + "subfield": subfield, + "is_repeated": is_repeated, + } + ) + + # Remove fields from the sample request which are not present in the runtime version of the dependency + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for subfield_to_delete in subfields_not_in_runtime: # pragma: NO COVER + field = subfield_to_delete.get("field") + field_repeated = subfield_to_delete.get("is_repeated") + subfield = subfield_to_delete.get("subfield") + if subfield: + if field_repeated: + for i in range( + 0, + len( + request_init[ + "reservations_perform_maintenance_request_resource" + ][field] + ), + ): + del request_init[ + "reservations_perform_maintenance_request_resource" + ][field][i][subfield] + else: + del request_init["reservations_perform_maintenance_request_resource"][ + field + ][subfield] + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = compute.Operation( + client_operation_id="client_operation_id_value", + creation_timestamp="creation_timestamp_value", + description="description_value", + end_time="end_time_value", + http_error_message="http_error_message_value", + http_error_status_code=2374, + id=205, + insert_time="insert_time_value", + kind="kind_value", + name="name_value", + operation_group_id="operation_group_id_value", + operation_type="operation_type_value", + progress=885, + region="region_value", + self_link="self_link_value", + start_time="start_time_value", + status=compute.Operation.Status.DONE, + status_message="status_message_value", + target_id=947, + target_link="target_link_value", + user="user_value", + zone="zone_value", + ) + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = compute.Operation.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value.content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = client.perform_maintenance(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, extended_operation.ExtendedOperation) + assert response.client_operation_id == "client_operation_id_value" + assert response.creation_timestamp == "creation_timestamp_value" + assert response.description == "description_value" + assert response.end_time == "end_time_value" + assert response.http_error_message == "http_error_message_value" + assert response.http_error_status_code == 2374 + assert response.id == 205 + assert response.insert_time == "insert_time_value" + assert response.kind == "kind_value" + assert response.name == "name_value" + assert response.operation_group_id == "operation_group_id_value" + assert response.operation_type == "operation_type_value" + assert response.progress == 885 + assert response.region == "region_value" + assert response.self_link == "self_link_value" + assert response.start_time == "start_time_value" + assert response.status == compute.Operation.Status.DONE + assert response.status_message == "status_message_value" + assert response.target_id == 947 + assert response.target_link == "target_link_value" + assert response.user == "user_value" + assert response.zone == "zone_value" + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_perform_maintenance_rest_interceptors(null_interceptor): + transport = transports.ReservationsRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ReservationsRestInterceptor(), + ) + client = ReservationsClient(transport=transport) + + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.ReservationsRestInterceptor, "post_perform_maintenance" + ) as post, mock.patch.object( + transports.ReservationsRestInterceptor, "post_perform_maintenance_with_metadata" + ) as post_with_metadata, mock.patch.object( + transports.ReservationsRestInterceptor, "pre_perform_maintenance" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = compute.PerformMaintenanceReservationRequest.pb( + compute.PerformMaintenanceReservationRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = compute.Operation.to_json(compute.Operation()) + req.return_value.content = return_value + + request = compute.PerformMaintenanceReservationRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = compute.Operation() + post_with_metadata.return_value = compute.Operation(), metadata + + client.perform_maintenance( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + def test_resize_rest_bad_request(request_type=compute.ResizeReservationRequest): client = ReservationsClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" @@ -5925,19 +6644,38 @@ def test_update_rest_call_success(request_type): }, "commitment": "commitment_value", "creation_timestamp": "creation_timestamp_value", + "deployment_type": "deployment_type_value", "description": "description_value", "id": 205, "kind": "kind_value", + "linked_commitments": [ + "linked_commitments_value1", + "linked_commitments_value2", + ], "name": "name_value", "reservation_sharing_policy": { "service_share_type": "service_share_type_value" }, "resource_policies": {}, "resource_status": { + "reservation_block_count": 2468, + "reservation_maintenance": { + "maintenance_ongoing_count": 2651, + "maintenance_pending_count": 2639, + "scheduling_type": "scheduling_type_value", + "upcoming_group_maintenance": { + "can_reschedule": True, + "latest_window_start_time": "latest_window_start_time_value", + "maintenance_status": "maintenance_status_value", + "type_": "type__value", + "window_end_time": "window_end_time_value", + "window_start_time": "window_start_time_value", + }, + }, "specific_sku_allocation": { "source_instance_template_id": "source_instance_template_id_value", "utilizations": {}, - } + }, }, "satisfies_pzs": True, "self_link": "self_link_value", @@ -6290,6 +7028,28 @@ def test_list_empty_call_rest(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_perform_maintenance_unary_empty_call_rest(): + client = ReservationsClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.perform_maintenance), "__call__" + ) as call: + client.perform_maintenance_unary(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = compute.PerformMaintenanceReservationRequest() + + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. def test_resize_unary_empty_call_rest(): @@ -6400,6 +7160,7 @@ def test_reservations_base_transport(): "get_iam_policy", "insert", "list", + "perform_maintenance", "resize", "set_iam_policy", "test_iam_permissions", @@ -6559,6 +7320,9 @@ def test_reservations_client_transport_session_collision(transport_name): session1 = client1.transport.list._session session2 = client2.transport.list._session assert session1 != session2 + session1 = client1.transport.perform_maintenance._session + session2 = client2.transport.perform_maintenance._session + assert session1 != session2 session1 = client1.transport.resize._session session2 = client2.transport.resize._session assert session1 != session2 diff --git a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_routers.py b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_routers.py index 98bceac298ff..6cf78e05bd87 100644 --- a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_routers.py +++ b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_routers.py @@ -7662,6 +7662,7 @@ def test_insert_rest_call_success(request_type): "max_ports_per_vm": 1733, "min_ports_per_vm": 1731, "name": "name_value", + "nat64_subnetworks": [{"name": "name_value"}], "nat_ip_allocate_option": "nat_ip_allocate_option_value", "nat_ips": ["nat_ips_value1", "nat_ips_value2"], "rules": [ @@ -7690,6 +7691,7 @@ def test_insert_rest_call_success(request_type): } ], "source_subnetwork_ip_ranges_to_nat": "source_subnetwork_ip_ranges_to_nat_value", + "source_subnetwork_ip_ranges_to_nat64": "source_subnetwork_ip_ranges_to_nat64_value", "subnetworks": [ { "name": "name_value", @@ -8427,6 +8429,7 @@ def test_patch_rest_call_success(request_type): "max_ports_per_vm": 1733, "min_ports_per_vm": 1731, "name": "name_value", + "nat64_subnetworks": [{"name": "name_value"}], "nat_ip_allocate_option": "nat_ip_allocate_option_value", "nat_ips": ["nat_ips_value1", "nat_ips_value2"], "rules": [ @@ -8455,6 +8458,7 @@ def test_patch_rest_call_success(request_type): } ], "source_subnetwork_ip_ranges_to_nat": "source_subnetwork_ip_ranges_to_nat_value", + "source_subnetwork_ip_ranges_to_nat64": "source_subnetwork_ip_ranges_to_nat64_value", "subnetworks": [ { "name": "name_value", @@ -9049,6 +9053,7 @@ def test_preview_rest_call_success(request_type): "max_ports_per_vm": 1733, "min_ports_per_vm": 1731, "name": "name_value", + "nat64_subnetworks": [{"name": "name_value"}], "nat_ip_allocate_option": "nat_ip_allocate_option_value", "nat_ips": ["nat_ips_value1", "nat_ips_value2"], "rules": [ @@ -9077,6 +9082,7 @@ def test_preview_rest_call_success(request_type): } ], "source_subnetwork_ip_ranges_to_nat": "source_subnetwork_ip_ranges_to_nat_value", + "source_subnetwork_ip_ranges_to_nat64": "source_subnetwork_ip_ranges_to_nat64_value", "subnetworks": [ { "name": "name_value", @@ -9370,6 +9376,7 @@ def test_update_rest_call_success(request_type): "max_ports_per_vm": 1733, "min_ports_per_vm": 1731, "name": "name_value", + "nat64_subnetworks": [{"name": "name_value"}], "nat_ip_allocate_option": "nat_ip_allocate_option_value", "nat_ips": ["nat_ips_value1", "nat_ips_value2"], "rules": [ @@ -9398,6 +9405,7 @@ def test_update_rest_call_success(request_type): } ], "source_subnetwork_ip_ranges_to_nat": "source_subnetwork_ip_ranges_to_nat_value", + "source_subnetwork_ip_ranges_to_nat64": "source_subnetwork_ip_ranges_to_nat64_value", "subnetworks": [ { "name": "name_value", diff --git a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_snapshots.py b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_snapshots.py index 664f56d289f6..636dd2d7c181 100644 --- a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_snapshots.py +++ b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_snapshots.py @@ -3450,6 +3450,7 @@ def test_get_rest_call_success(request_type): disk_size_gb=1261, download_bytes=1502, enable_confidential_compute=True, + guest_flush=True, id=205, kind="kind_value", label_fingerprint="label_fingerprint_value", @@ -3497,6 +3498,7 @@ def test_get_rest_call_success(request_type): assert response.disk_size_gb == 1261 assert response.download_bytes == 1502 assert response.enable_confidential_compute is True + assert response.guest_flush is True assert response.id == 205 assert response.kind == "kind_value" assert response.label_fingerprint == "label_fingerprint_value" @@ -3764,6 +3766,7 @@ def test_insert_rest_call_success(request_type): "disk_size_gb": 1261, "download_bytes": 1502, "enable_confidential_compute": True, + "guest_flush": True, "guest_os_features": [{"type_": "type__value"}], "id": 205, "kind": "kind_value", diff --git a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_url_maps.py b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_url_maps.py index bc6d921fa044..f28823e0191f 100644 --- a/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_url_maps.py +++ b/packages/google-cloud-compute/tests/unit/gapic/compute_v1/test_url_maps.py @@ -2317,7 +2317,7 @@ def test_invalidate_cache_rest_flattened(): project="project_value", url_map="url_map_value", cache_invalidation_rule_resource=compute.CacheInvalidationRule( - host="host_value" + cache_tags=["cache_tags_value"] ), ) mock_args.update(sample_request) @@ -2359,7 +2359,7 @@ def test_invalidate_cache_rest_flattened_error(transport: str = "rest"): project="project_value", url_map="url_map_value", cache_invalidation_rule_resource=compute.CacheInvalidationRule( - host="host_value" + cache_tags=["cache_tags_value"] ), ) @@ -2525,7 +2525,7 @@ def test_invalidate_cache_unary_rest_flattened(): project="project_value", url_map="url_map_value", cache_invalidation_rule_resource=compute.CacheInvalidationRule( - host="host_value" + cache_tags=["cache_tags_value"] ), ) mock_args.update(sample_request) @@ -2567,7 +2567,7 @@ def test_invalidate_cache_unary_rest_flattened_error(transport: str = "rest"): project="project_value", url_map="url_map_value", cache_invalidation_rule_resource=compute.CacheInvalidationRule( - host="host_value" + cache_tags=["cache_tags_value"] ), ) @@ -4817,6 +4817,7 @@ def test_invalidate_cache_rest_call_success(request_type): # send a request that will satisfy transcoding request_init = {"project": "sample1", "url_map": "sample2"} request_init["cache_invalidation_rule_resource"] = { + "cache_tags": ["cache_tags_value1", "cache_tags_value2"], "host": "host_value", "path": "path_value", }