diff --git a/google/cloud/asset/__init__.py b/google/cloud/asset/__init__.py index ede0c218..b4309178 100644 --- a/google/cloud/asset/__init__.py +++ b/google/cloud/asset/__init__.py @@ -19,12 +19,17 @@ AssetServiceAsyncClient, ) +from google.cloud.asset_v1.types.asset_service import ( + AnalyzeIamPolicyLongrunningMetadata, +) from google.cloud.asset_v1.types.asset_service import AnalyzeIamPolicyLongrunningRequest from google.cloud.asset_v1.types.asset_service import ( AnalyzeIamPolicyLongrunningResponse, ) from google.cloud.asset_v1.types.asset_service import AnalyzeIamPolicyRequest from google.cloud.asset_v1.types.asset_service import AnalyzeIamPolicyResponse +from google.cloud.asset_v1.types.asset_service import AnalyzeMoveRequest +from google.cloud.asset_v1.types.asset_service import AnalyzeMoveResponse from google.cloud.asset_v1.types.asset_service import BatchGetAssetsHistoryRequest from google.cloud.asset_v1.types.asset_service import BatchGetAssetsHistoryResponse from google.cloud.asset_v1.types.asset_service import BigQueryDestination @@ -43,6 +48,9 @@ from google.cloud.asset_v1.types.asset_service import ListAssetsResponse from google.cloud.asset_v1.types.asset_service import ListFeedsRequest from google.cloud.asset_v1.types.asset_service import ListFeedsResponse +from google.cloud.asset_v1.types.asset_service import MoveAnalysis +from google.cloud.asset_v1.types.asset_service import MoveAnalysisResult +from google.cloud.asset_v1.types.asset_service import MoveImpact from google.cloud.asset_v1.types.asset_service import OutputConfig from google.cloud.asset_v1.types.asset_service import OutputResult from google.cloud.asset_v1.types.asset_service import PartitionSpec @@ -54,6 +62,7 @@ from google.cloud.asset_v1.types.asset_service import UpdateFeedRequest from google.cloud.asset_v1.types.asset_service import ContentType from google.cloud.asset_v1.types.assets import Asset +from google.cloud.asset_v1.types.assets import AttachedResource from google.cloud.asset_v1.types.assets import ConditionEvaluation from google.cloud.asset_v1.types.assets import IamPolicyAnalysisResult from google.cloud.asset_v1.types.assets import IamPolicyAnalysisState @@ -62,14 +71,18 @@ from google.cloud.asset_v1.types.assets import ResourceSearchResult from google.cloud.asset_v1.types.assets import TemporalAsset from google.cloud.asset_v1.types.assets import TimeWindow +from google.cloud.asset_v1.types.assets import VersionedResource __all__ = ( "AssetServiceClient", "AssetServiceAsyncClient", + "AnalyzeIamPolicyLongrunningMetadata", "AnalyzeIamPolicyLongrunningRequest", "AnalyzeIamPolicyLongrunningResponse", "AnalyzeIamPolicyRequest", "AnalyzeIamPolicyResponse", + "AnalyzeMoveRequest", + "AnalyzeMoveResponse", "BatchGetAssetsHistoryRequest", "BatchGetAssetsHistoryResponse", "BigQueryDestination", @@ -88,6 +101,9 @@ "ListAssetsResponse", "ListFeedsRequest", "ListFeedsResponse", + "MoveAnalysis", + "MoveAnalysisResult", + "MoveImpact", "OutputConfig", "OutputResult", "PartitionSpec", @@ -99,6 +115,7 @@ "UpdateFeedRequest", "ContentType", "Asset", + "AttachedResource", "ConditionEvaluation", "IamPolicyAnalysisResult", "IamPolicyAnalysisState", @@ -107,4 +124,5 @@ "ResourceSearchResult", "TemporalAsset", "TimeWindow", + "VersionedResource", ) diff --git a/google/cloud/asset_v1/__init__.py b/google/cloud/asset_v1/__init__.py index 92bbf9e9..ada8ad1c 100644 --- a/google/cloud/asset_v1/__init__.py +++ b/google/cloud/asset_v1/__init__.py @@ -17,10 +17,13 @@ from .services.asset_service import AssetServiceClient from .services.asset_service import AssetServiceAsyncClient +from .types.asset_service import AnalyzeIamPolicyLongrunningMetadata from .types.asset_service import AnalyzeIamPolicyLongrunningRequest from .types.asset_service import AnalyzeIamPolicyLongrunningResponse from .types.asset_service import AnalyzeIamPolicyRequest from .types.asset_service import AnalyzeIamPolicyResponse +from .types.asset_service import AnalyzeMoveRequest +from .types.asset_service import AnalyzeMoveResponse from .types.asset_service import BatchGetAssetsHistoryRequest from .types.asset_service import BatchGetAssetsHistoryResponse from .types.asset_service import BigQueryDestination @@ -39,6 +42,9 @@ from .types.asset_service import ListAssetsResponse from .types.asset_service import ListFeedsRequest from .types.asset_service import ListFeedsResponse +from .types.asset_service import MoveAnalysis +from .types.asset_service import MoveAnalysisResult +from .types.asset_service import MoveImpact from .types.asset_service import OutputConfig from .types.asset_service import OutputResult from .types.asset_service import PartitionSpec @@ -50,6 +56,7 @@ from .types.asset_service import UpdateFeedRequest from .types.asset_service import ContentType from .types.assets import Asset +from .types.assets import AttachedResource from .types.assets import ConditionEvaluation from .types.assets import IamPolicyAnalysisResult from .types.assets import IamPolicyAnalysisState @@ -58,15 +65,20 @@ from .types.assets import ResourceSearchResult from .types.assets import TemporalAsset from .types.assets import TimeWindow +from .types.assets import VersionedResource __all__ = ( "AssetServiceAsyncClient", + "AnalyzeIamPolicyLongrunningMetadata", "AnalyzeIamPolicyLongrunningRequest", "AnalyzeIamPolicyLongrunningResponse", "AnalyzeIamPolicyRequest", "AnalyzeIamPolicyResponse", + "AnalyzeMoveRequest", + "AnalyzeMoveResponse", "Asset", "AssetServiceClient", + "AttachedResource", "BatchGetAssetsHistoryRequest", "BatchGetAssetsHistoryResponse", "BigQueryDestination", @@ -90,6 +102,9 @@ "ListAssetsResponse", "ListFeedsRequest", "ListFeedsResponse", + "MoveAnalysis", + "MoveAnalysisResult", + "MoveImpact", "OutputConfig", "OutputResult", "PartitionSpec", @@ -103,4 +118,5 @@ "TemporalAsset", "TimeWindow", "UpdateFeedRequest", + "VersionedResource", ) diff --git a/google/cloud/asset_v1/gapic_metadata.json b/google/cloud/asset_v1/gapic_metadata.json index eebf25a1..dea0335c 100644 --- a/google/cloud/asset_v1/gapic_metadata.json +++ b/google/cloud/asset_v1/gapic_metadata.json @@ -20,6 +20,11 @@ "analyze_iam_policy_longrunning" ] }, + "AnalyzeMove": { + "methods": [ + "analyze_move" + ] + }, "BatchGetAssetsHistory": { "methods": [ "batch_get_assets_history" @@ -85,6 +90,11 @@ "analyze_iam_policy_longrunning" ] }, + "AnalyzeMove": { + "methods": [ + "analyze_move" + ] + }, "BatchGetAssetsHistory": { "methods": [ "batch_get_assets_history" diff --git a/google/cloud/asset_v1/services/asset_service/async_client.py b/google/cloud/asset_v1/services/asset_service/async_client.py index b56b0f30..5546a37b 100644 --- a/google/cloud/asset_v1/services/asset_service/async_client.py +++ b/google/cloud/asset_v1/services/asset_service/async_client.py @@ -864,8 +864,8 @@ async def search_all_resources( the word "key". - ``state:ACTIVE`` to find Cloud resources whose state contains "ACTIVE" as a word. - - ``NOT state:ACTIVE`` to find {{gcp_name}} resources - whose state doesn't contain "ACTIVE" as a word. + - ``NOT state:ACTIVE`` to find Cloud resources whose + state doesn't contain "ACTIVE" as a word. - ``createTime<1609459200`` to find Cloud resources that were created before "2021-01-01 00:00:00 UTC". 1609459200 is the epoch timestamp of "2021-01-01 @@ -1221,8 +1221,8 @@ async def analyze_iam_policy_longrunning( [google.longrunning.Operation][google.longrunning.Operation], which allows you to track the operation status. We recommend intervals of at least 2 seconds with exponential backoff retry - to poll the operation result. The metadata contains the request - to help callers to map responses to requests. + to poll the operation result. The metadata contains the metadata + for the long-running operation. Args: request (:class:`google.cloud.asset_v1.types.AnalyzeIamPolicyLongrunningRequest`): @@ -1271,12 +1271,67 @@ async def analyze_iam_policy_longrunning( response, self._client._transport.operations_client, asset_service.AnalyzeIamPolicyLongrunningResponse, - metadata_type=asset_service.AnalyzeIamPolicyLongrunningRequest, + metadata_type=asset_service.AnalyzeIamPolicyLongrunningMetadata, ) # Done; return the response. return response + async def analyze_move( + self, + request: asset_service.AnalyzeMoveRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> asset_service.AnalyzeMoveResponse: + r"""Analyze moving a resource to a specified destination + without kicking off the actual move. The analysis is + best effort depending on the user's permissions of + viewing different hierarchical policies and + configurations. The policies and configuration are + subject to change before the actual resource migration + takes place. + + Args: + request (:class:`google.cloud.asset_v1.types.AnalyzeMoveRequest`): + The request object. The request message for performing + resource move analysis. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.asset_v1.types.AnalyzeMoveResponse: + The response message for resource + move analysis. + + """ + # Create or coerce a protobuf request object. + request = asset_service.AnalyzeMoveRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.analyze_move, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Done; return the response. + return response + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/asset_v1/services/asset_service/client.py b/google/cloud/asset_v1/services/asset_service/client.py index 38c7ce3d..6459c846 100644 --- a/google/cloud/asset_v1/services/asset_service/client.py +++ b/google/cloud/asset_v1/services/asset_service/client.py @@ -1005,8 +1005,8 @@ def search_all_resources( the word "key". - ``state:ACTIVE`` to find Cloud resources whose state contains "ACTIVE" as a word. - - ``NOT state:ACTIVE`` to find {{gcp_name}} resources - whose state doesn't contain "ACTIVE" as a word. + - ``NOT state:ACTIVE`` to find Cloud resources whose + state doesn't contain "ACTIVE" as a word. - ``createTime<1609459200`` to find Cloud resources that were created before "2021-01-01 00:00:00 UTC". 1609459200 is the epoch timestamp of "2021-01-01 @@ -1336,8 +1336,8 @@ def analyze_iam_policy_longrunning( [google.longrunning.Operation][google.longrunning.Operation], which allows you to track the operation status. We recommend intervals of at least 2 seconds with exponential backoff retry - to poll the operation result. The metadata contains the request - to help callers to map responses to requests. + to poll the operation result. The metadata contains the metadata + for the long-running operation. Args: request (google.cloud.asset_v1.types.AnalyzeIamPolicyLongrunningRequest): @@ -1389,12 +1389,68 @@ def analyze_iam_policy_longrunning( response, self._transport.operations_client, asset_service.AnalyzeIamPolicyLongrunningResponse, - metadata_type=asset_service.AnalyzeIamPolicyLongrunningRequest, + metadata_type=asset_service.AnalyzeIamPolicyLongrunningMetadata, ) # Done; return the response. return response + def analyze_move( + self, + request: asset_service.AnalyzeMoveRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> asset_service.AnalyzeMoveResponse: + r"""Analyze moving a resource to a specified destination + without kicking off the actual move. The analysis is + best effort depending on the user's permissions of + viewing different hierarchical policies and + configurations. The policies and configuration are + subject to change before the actual resource migration + takes place. + + Args: + request (google.cloud.asset_v1.types.AnalyzeMoveRequest): + The request object. The request message for performing + resource move analysis. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.asset_v1.types.AnalyzeMoveResponse: + The response message for resource + move analysis. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a asset_service.AnalyzeMoveRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, asset_service.AnalyzeMoveRequest): + request = asset_service.AnalyzeMoveRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.analyze_move] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Done; return the response. + return response + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/asset_v1/services/asset_service/transports/base.py b/google/cloud/asset_v1/services/asset_service/transports/base.py index e15d7266..263026e0 100644 --- a/google/cloud/asset_v1/services/asset_service/transports/base.py +++ b/google/cloud/asset_v1/services/asset_service/transports/base.py @@ -286,6 +286,9 @@ def _prep_wrapped_messages(self, client_info): default_timeout=60.0, client_info=client_info, ), + self.analyze_move: gapic_v1.method.wrap_method( + self.analyze_move, default_timeout=None, client_info=client_info, + ), } @property @@ -418,5 +421,17 @@ def analyze_iam_policy_longrunning( ]: raise NotImplementedError() + @property + def analyze_move( + self, + ) -> Callable[ + [asset_service.AnalyzeMoveRequest], + Union[ + asset_service.AnalyzeMoveResponse, + Awaitable[asset_service.AnalyzeMoveResponse], + ], + ]: + raise NotImplementedError() + __all__ = ("AssetServiceTransport",) diff --git a/google/cloud/asset_v1/services/asset_service/transports/grpc.py b/google/cloud/asset_v1/services/asset_service/transports/grpc.py index 177e4a3a..57211806 100644 --- a/google/cloud/asset_v1/services/asset_service/transports/grpc.py +++ b/google/cloud/asset_v1/services/asset_service/transports/grpc.py @@ -585,8 +585,8 @@ def analyze_iam_policy_longrunning( [google.longrunning.Operation][google.longrunning.Operation], which allows you to track the operation status. We recommend intervals of at least 2 seconds with exponential backoff retry - to poll the operation result. The metadata contains the request - to help callers to map responses to requests. + to poll the operation result. The metadata contains the metadata + for the long-running operation. Returns: Callable[[~.AnalyzeIamPolicyLongrunningRequest], @@ -608,5 +608,39 @@ def analyze_iam_policy_longrunning( ) return self._stubs["analyze_iam_policy_longrunning"] + @property + def analyze_move( + self, + ) -> Callable[ + [asset_service.AnalyzeMoveRequest], asset_service.AnalyzeMoveResponse + ]: + r"""Return a callable for the analyze move method over gRPC. + + Analyze moving a resource to a specified destination + without kicking off the actual move. The analysis is + best effort depending on the user's permissions of + viewing different hierarchical policies and + configurations. The policies and configuration are + subject to change before the actual resource migration + takes place. + + Returns: + Callable[[~.AnalyzeMoveRequest], + ~.AnalyzeMoveResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "analyze_move" not in self._stubs: + self._stubs["analyze_move"] = self.grpc_channel.unary_unary( + "/google.cloud.asset.v1.AssetService/AnalyzeMove", + request_serializer=asset_service.AnalyzeMoveRequest.serialize, + response_deserializer=asset_service.AnalyzeMoveResponse.deserialize, + ) + return self._stubs["analyze_move"] + __all__ = ("AssetServiceGrpcTransport",) diff --git a/google/cloud/asset_v1/services/asset_service/transports/grpc_asyncio.py b/google/cloud/asset_v1/services/asset_service/transports/grpc_asyncio.py index 7df1ccb4..74e79b1e 100644 --- a/google/cloud/asset_v1/services/asset_service/transports/grpc_asyncio.py +++ b/google/cloud/asset_v1/services/asset_service/transports/grpc_asyncio.py @@ -600,8 +600,8 @@ def analyze_iam_policy_longrunning( [google.longrunning.Operation][google.longrunning.Operation], which allows you to track the operation status. We recommend intervals of at least 2 seconds with exponential backoff retry - to poll the operation result. The metadata contains the request - to help callers to map responses to requests. + to poll the operation result. The metadata contains the metadata + for the long-running operation. Returns: Callable[[~.AnalyzeIamPolicyLongrunningRequest], @@ -623,5 +623,39 @@ def analyze_iam_policy_longrunning( ) return self._stubs["analyze_iam_policy_longrunning"] + @property + def analyze_move( + self, + ) -> Callable[ + [asset_service.AnalyzeMoveRequest], Awaitable[asset_service.AnalyzeMoveResponse] + ]: + r"""Return a callable for the analyze move method over gRPC. + + Analyze moving a resource to a specified destination + without kicking off the actual move. The analysis is + best effort depending on the user's permissions of + viewing different hierarchical policies and + configurations. The policies and configuration are + subject to change before the actual resource migration + takes place. + + Returns: + Callable[[~.AnalyzeMoveRequest], + Awaitable[~.AnalyzeMoveResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "analyze_move" not in self._stubs: + self._stubs["analyze_move"] = self.grpc_channel.unary_unary( + "/google.cloud.asset.v1.AssetService/AnalyzeMove", + request_serializer=asset_service.AnalyzeMoveRequest.serialize, + response_deserializer=asset_service.AnalyzeMoveResponse.deserialize, + ) + return self._stubs["analyze_move"] + __all__ = ("AssetServiceGrpcAsyncIOTransport",) diff --git a/google/cloud/asset_v1/types/__init__.py b/google/cloud/asset_v1/types/__init__.py index 600d11c3..4a220650 100644 --- a/google/cloud/asset_v1/types/__init__.py +++ b/google/cloud/asset_v1/types/__init__.py @@ -14,10 +14,13 @@ # limitations under the License. # from .asset_service import ( + AnalyzeIamPolicyLongrunningMetadata, AnalyzeIamPolicyLongrunningRequest, AnalyzeIamPolicyLongrunningResponse, AnalyzeIamPolicyRequest, AnalyzeIamPolicyResponse, + AnalyzeMoveRequest, + AnalyzeMoveResponse, BatchGetAssetsHistoryRequest, BatchGetAssetsHistoryResponse, BigQueryDestination, @@ -36,6 +39,9 @@ ListAssetsResponse, ListFeedsRequest, ListFeedsResponse, + MoveAnalysis, + MoveAnalysisResult, + MoveImpact, OutputConfig, OutputResult, PartitionSpec, @@ -49,6 +55,7 @@ ) from .assets import ( Asset, + AttachedResource, ConditionEvaluation, IamPolicyAnalysisResult, IamPolicyAnalysisState, @@ -57,13 +64,17 @@ ResourceSearchResult, TemporalAsset, TimeWindow, + VersionedResource, ) __all__ = ( + "AnalyzeIamPolicyLongrunningMetadata", "AnalyzeIamPolicyLongrunningRequest", "AnalyzeIamPolicyLongrunningResponse", "AnalyzeIamPolicyRequest", "AnalyzeIamPolicyResponse", + "AnalyzeMoveRequest", + "AnalyzeMoveResponse", "BatchGetAssetsHistoryRequest", "BatchGetAssetsHistoryResponse", "BigQueryDestination", @@ -82,6 +93,9 @@ "ListAssetsResponse", "ListFeedsRequest", "ListFeedsResponse", + "MoveAnalysis", + "MoveAnalysisResult", + "MoveImpact", "OutputConfig", "OutputResult", "PartitionSpec", @@ -93,6 +107,7 @@ "UpdateFeedRequest", "ContentType", "Asset", + "AttachedResource", "ConditionEvaluation", "IamPolicyAnalysisResult", "IamPolicyAnalysisState", @@ -101,4 +116,5 @@ "ResourceSearchResult", "TemporalAsset", "TimeWindow", + "VersionedResource", ) diff --git a/google/cloud/asset_v1/types/asset_service.py b/google/cloud/asset_v1/types/asset_service.py index bb0dd094..6794d437 100644 --- a/google/cloud/asset_v1/types/asset_service.py +++ b/google/cloud/asset_v1/types/asset_service.py @@ -19,6 +19,7 @@ from google.protobuf import duration_pb2 # type: ignore from google.protobuf import field_mask_pb2 # type: ignore from google.protobuf import timestamp_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore from google.type import expr_pb2 # type: ignore @@ -26,6 +27,7 @@ package="google.cloud.asset.v1", manifest={ "ContentType", + "AnalyzeIamPolicyLongrunningMetadata", "ExportAssetsRequest", "ExportAssetsResponse", "ListAssetsRequest", @@ -57,6 +59,11 @@ "IamPolicyAnalysisOutputConfig", "AnalyzeIamPolicyLongrunningRequest", "AnalyzeIamPolicyLongrunningResponse", + "AnalyzeMoveRequest", + "AnalyzeMoveResponse", + "MoveAnalysis", + "MoveAnalysisResult", + "MoveImpact", }, ) @@ -71,6 +78,18 @@ class ContentType(proto.Enum): OS_INVENTORY = 6 +class AnalyzeIamPolicyLongrunningMetadata(proto.Message): + r"""Represents the metadata of the longrunning operation for the + AnalyzeIamPolicyLongrunning rpc. + + Attributes: + create_time (google.protobuf.timestamp_pb2.Timestamp): + The time the operation was created. + """ + + create_time = proto.Field(proto.MESSAGE, number=1, message=timestamp_pb2.Timestamp,) + + class ExportAssetsRequest(proto.Message): r"""Export asset request. Attributes: @@ -654,7 +673,7 @@ class Feed(proto.Message): optional. See our `user - guide `__ + guide `__ for detailed instructions. """ @@ -713,8 +732,8 @@ class SearchAllResourcesRequest(proto.Message): word "key". - ``state:ACTIVE`` to find Cloud resources whose state contains "ACTIVE" as a word. - - ``NOT state:ACTIVE`` to find {{gcp_name}} resources whose - state doesn't contain "ACTIVE" as a word. + - ``NOT state:ACTIVE`` to find Cloud resources whose state + doesn't contain "ACTIVE" as a word. - ``createTime<1609459200`` to find Cloud resources that were created before "2021-01-01 00:00:00 UTC". 1609459200 is the epoch timestamp of "2021-01-01 00:00:00 UTC" in @@ -781,10 +800,42 @@ class SearchAllResourcesRequest(proto.Message): - updateTime - state - parentFullResourceName - - parentAssetType All the other fields such as repeated - fields (e.g., ``networkTags``), map fields (e.g., - ``labels``) and struct fields (e.g., - ``additionalAttributes``) are not supported. + - parentAssetType + + All the other fields such as repeated fields (e.g., + ``networkTags``), map fields (e.g., ``labels``) and struct + fields (e.g., ``additionalAttributes``) are not supported. + read_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. A comma-separated list of fields specifying which + fields to be returned in ResourceSearchResult. Only '*' or + combination of top level fields can be specified. Field + names of both snake_case and camelCase are supported. + Examples: ``"*"``, ``"name,location"``, + ``"name,versionedResources"``. + + The read_mask paths must be valid field paths listed but not + limited to (both snake_case and camelCase are supported): + + - name + - assetType + - project + - displayName + - description + - location + - labels + - networkTags + - kmsKey + - createTime + - updateTime + - state + - additionalAttributes + - versionedResources + + If read_mask is not specified, all fields except + versionedResources will be returned. If only '*' is + specified, all fields including versionedResources will be + returned. Any invalid field path will trigger + INVALID_ARGUMENT error. """ scope = proto.Field(proto.STRING, number=1,) @@ -793,6 +844,7 @@ class SearchAllResourcesRequest(proto.Message): page_size = proto.Field(proto.INT32, number=4,) page_token = proto.Field(proto.STRING, number=5,) order_by = proto.Field(proto.STRING, number=6,) + read_mask = proto.Field(proto.MESSAGE, number=8, message=field_mask_pb2.FieldMask,) class SearchAllResourcesResponse(proto.Message): @@ -1387,4 +1439,106 @@ class AnalyzeIamPolicyLongrunningResponse(proto.Message): """ +class AnalyzeMoveRequest(proto.Message): + r"""The request message for performing resource move analysis. + Attributes: + resource (str): + Required. Name of the resource to perform the + analysis against. Only GCP Project are supported + as of today. Hence, this can only be Project ID + (such as "projects/my-project-id") or a Project + Number (such as "projects/12345"). + destination_parent (str): + Required. Name of the GCP Folder or + Organization to reparent the target resource. + The analysis will be performed against + hypothetically moving the resource to this + specified desitination parent. This can only be + a Folder number (such as "folders/123") or an + Organization number (such as + "organizations/123"). + view (google.cloud.asset_v1.types.AnalyzeMoveRequest.AnalysisView): + Analysis view indicating what information + should be included in the analysis response. If + unspecified, the default view is FULL. + """ + + class AnalysisView(proto.Enum): + r"""View enum for supporting partial analysis responses.""" + ANALYSIS_VIEW_UNSPECIFIED = 0 + FULL = 1 + BASIC = 2 + + resource = proto.Field(proto.STRING, number=1,) + destination_parent = proto.Field(proto.STRING, number=2,) + view = proto.Field(proto.ENUM, number=3, enum=AnalysisView,) + + +class AnalyzeMoveResponse(proto.Message): + r"""The response message for resource move analysis. + Attributes: + move_analysis (Sequence[google.cloud.asset_v1.types.MoveAnalysis]): + The list of analyses returned from performing + the intended resource move analysis. The + analysis is grouped by different Cloud services. + """ + + move_analysis = proto.RepeatedField( + proto.MESSAGE, number=1, message="MoveAnalysis", + ) + + +class MoveAnalysis(proto.Message): + r"""A message to group the analysis information. + Attributes: + display_name (str): + The user friendly display name of the + analysis. E.g. IAM, Organization Policy etc. + analysis (google.cloud.asset_v1.types.MoveAnalysisResult): + Analysis result of moving the target + resource. + error (google.rpc.status_pb2.Status): + Description of error encountered when + performing the analysis. + """ + + display_name = proto.Field(proto.STRING, number=1,) + analysis = proto.Field( + proto.MESSAGE, number=2, oneof="result", message="MoveAnalysisResult", + ) + error = proto.Field( + proto.MESSAGE, number=3, oneof="result", message=status_pb2.Status, + ) + + +class MoveAnalysisResult(proto.Message): + r"""An analysis result including blockers and warnings. + Attributes: + blockers (Sequence[google.cloud.asset_v1.types.MoveImpact]): + Blocking information that would prevent the + target resource from moving to the specified + destination at runtime. + warnings (Sequence[google.cloud.asset_v1.types.MoveImpact]): + Warning information indicating that moving + the target resource to the specified destination + might be unsafe. This can include important + policy information and configuration changes, + but will not block moves at runtime. + """ + + blockers = proto.RepeatedField(proto.MESSAGE, number=1, message="MoveImpact",) + warnings = proto.RepeatedField(proto.MESSAGE, number=2, message="MoveImpact",) + + +class MoveImpact(proto.Message): + r"""A message to group impacts of moving the target resource. + Attributes: + detail (str): + User friendly impact detail in a free form + message. + """ + + detail = proto.Field(proto.STRING, number=1,) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/asset_v1/types/assets.py b/google/cloud/asset_v1/types/assets.py index 5778741c..a55efe1e 100644 --- a/google/cloud/asset_v1/types/assets.py +++ b/google/cloud/asset_v1/types/assets.py @@ -34,6 +34,8 @@ "Asset", "Resource", "ResourceSearchResult", + "VersionedResource", + "AttachedResource", "IamPolicySearchResult", "IamPolicyAnalysisState", "ConditionEvaluation", @@ -464,6 +466,25 @@ class ResourceSearchResult(proto.Message): - use a field query. Example: ``parentFullResourceName:"project-name"`` - use a free text query. Example: ``project-name`` + versioned_resources (Sequence[google.cloud.asset_v1.types.VersionedResource]): + Versioned resource representations of this resource. This is + repeated because there could be multiple versions of + resource representations during version migration. + + This ``versioned_resources`` field is not searchable. Some + attributes of the resource representations are exposed in + ``additional_attributes`` field, so as to allow users to + search on them. + attached_resources (Sequence[google.cloud.asset_v1.types.AttachedResource]): + Attached resources of this resource. For example, an + OSConfig Inventory is an attached resource of a Compute + Instance. This field is repeated because a resource could + have multiple attached resources. + + This ``attached_resources`` field is not searchable. Some + attributes of the attached resources are exposed in + ``additional_attributes`` field, so as to allow users to + search on them. parent_asset_type (str): The type of this resource's immediate parent, if there is one. @@ -498,9 +519,73 @@ class ResourceSearchResult(proto.Message): proto.MESSAGE, number=9, message=struct_pb2.Struct, ) parent_full_resource_name = proto.Field(proto.STRING, number=19,) + versioned_resources = proto.RepeatedField( + proto.MESSAGE, number=16, message="VersionedResource", + ) + attached_resources = proto.RepeatedField( + proto.MESSAGE, number=20, message="AttachedResource", + ) parent_asset_type = proto.Field(proto.STRING, number=103,) +class VersionedResource(proto.Message): + r"""Resource representation as defined by the corresponding + service providing the resource for a given API version. + + Attributes: + version (str): + API version of the resource. + + Example: If the resource is an instance provided by Compute + Engine v1 API as defined in + ``https://cloud.google.com/compute/docs/reference/rest/v1/instances``, + version will be "v1". + resource (google.protobuf.struct_pb2.Struct): + JSON representation of the resource as defined by the + corresponding service providing this resource. + + Example: If the resource is an instance provided by Compute + Engine, this field will contain the JSON representation of + the instance as defined by Compute Engine: + ``https://cloud.google.com/compute/docs/reference/rest/v1/instances``. + + You can find the resource definition for each supported + resource type in this table: + ``https://cloud.google.com/asset-inventory/docs/supported-asset-types#searchable_asset_types`` + """ + + version = proto.Field(proto.STRING, number=1,) + resource = proto.Field(proto.MESSAGE, number=2, message=struct_pb2.Struct,) + + +class AttachedResource(proto.Message): + r"""Attached resource representation, which is defined by the + corresponding service provider. It represents an attached + resource's payload. + + Attributes: + asset_type (str): + The type of this attached resource. + + Example: ``osconfig.googleapis.com/Inventory`` + + You can find the supported attached asset types of each + resource in this table: + ``https://cloud.google.com/asset-inventory/docs/supported-asset-types#searchable_asset_types`` + versioned_resources (Sequence[google.cloud.asset_v1.types.VersionedResource]): + Versioned resource representations of this + attached resource. This is repeated because + there could be multiple versions of the attached + resource representations during version + migration. + """ + + asset_type = proto.Field(proto.STRING, number=1,) + versioned_resources = proto.RepeatedField( + proto.MESSAGE, number=3, message="VersionedResource", + ) + + class IamPolicySearchResult(proto.Message): r"""A result of IAM Policy search, containing information of an IAM policy. diff --git a/scripts/fixup_asset_v1_keywords.py b/scripts/fixup_asset_v1_keywords.py index 4a9e79e9..5d5abef3 100644 --- a/scripts/fixup_asset_v1_keywords.py +++ b/scripts/fixup_asset_v1_keywords.py @@ -41,6 +41,7 @@ class assetCallTransformer(cst.CSTTransformer): METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { 'analyze_iam_policy': ('analysis_query', 'execution_timeout', ), 'analyze_iam_policy_longrunning': ('analysis_query', 'output_config', ), + 'analyze_move': ('resource', 'destination_parent', 'view', ), 'batch_get_assets_history': ('parent', 'asset_names', 'content_type', 'read_time_window', ), 'create_feed': ('parent', 'feed_id', 'feed', ), 'delete_feed': ('name', ), @@ -49,7 +50,7 @@ class assetCallTransformer(cst.CSTTransformer): 'list_assets': ('parent', 'read_time', 'asset_types', 'content_type', 'page_size', 'page_token', ), 'list_feeds': ('parent', ), 'search_all_iam_policies': ('scope', 'query', 'page_size', 'page_token', 'asset_types', 'order_by', ), - 'search_all_resources': ('scope', 'query', 'asset_types', 'page_size', 'page_token', 'order_by', ), + 'search_all_resources': ('scope', 'query', 'asset_types', 'page_size', 'page_token', 'order_by', 'read_mask', ), 'update_feed': ('feed', 'update_mask', ), } diff --git a/tests/unit/gapic/asset_v1/test_asset_service.py b/tests/unit/gapic/asset_v1/test_asset_service.py index d79cf14f..17926e1e 100644 --- a/tests/unit/gapic/asset_v1/test_asset_service.py +++ b/tests/unit/gapic/asset_v1/test_asset_service.py @@ -3149,6 +3149,136 @@ async def test_analyze_iam_policy_longrunning_field_headers_async(): ) in kw["metadata"] +def test_analyze_move( + transport: str = "grpc", request_type=asset_service.AnalyzeMoveRequest +): + client = AssetServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.analyze_move), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = asset_service.AnalyzeMoveResponse() + response = client.analyze_move(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == asset_service.AnalyzeMoveRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, asset_service.AnalyzeMoveResponse) + + +def test_analyze_move_from_dict(): + test_analyze_move(request_type=dict) + + +def test_analyze_move_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = AssetServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.analyze_move), "__call__") as call: + client.analyze_move() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == asset_service.AnalyzeMoveRequest() + + +@pytest.mark.asyncio +async def test_analyze_move_async( + transport: str = "grpc_asyncio", request_type=asset_service.AnalyzeMoveRequest +): + client = AssetServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.analyze_move), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + asset_service.AnalyzeMoveResponse() + ) + response = await client.analyze_move(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == asset_service.AnalyzeMoveRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, asset_service.AnalyzeMoveResponse) + + +@pytest.mark.asyncio +async def test_analyze_move_async_from_dict(): + await test_analyze_move_async(request_type=dict) + + +def test_analyze_move_field_headers(): + client = AssetServiceClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = asset_service.AnalyzeMoveRequest() + + request.resource = "resource/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.analyze_move), "__call__") as call: + call.return_value = asset_service.AnalyzeMoveResponse() + client.analyze_move(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "resource=resource/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_analyze_move_field_headers_async(): + client = AssetServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = asset_service.AnalyzeMoveRequest() + + request.resource = "resource/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.analyze_move), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + asset_service.AnalyzeMoveResponse() + ) + await client.analyze_move(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "resource=resource/value",) in kw["metadata"] + + def test_credentials_transport_error(): # It is an error to provide credentials and a transport instance. transport = transports.AssetServiceGrpcTransport( @@ -3258,6 +3388,7 @@ def test_asset_service_base_transport(): "search_all_iam_policies", "analyze_iam_policy", "analyze_iam_policy_longrunning", + "analyze_move", ) for method in methods: with pytest.raises(NotImplementedError):