diff --git a/mockgcp/mockcompute/networksv1.go b/mockgcp/mockcompute/networksv1.go index da3c4cecb0..890e2e2a8f 100644 --- a/mockgcp/mockcompute/networksv1.go +++ b/mockgcp/mockcompute/networksv1.go @@ -43,6 +43,9 @@ func (s *NetworksV1) Get(ctx context.Context, req *pb.GetNetworkRequest) (*pb.Ne obj := &pb.Network{} if err := s.storage.Get(ctx, fqn, obj); err != nil { + if status.Code(err) == codes.NotFound { + return nil, status.Errorf(codes.NotFound, "The resource '%s' was not found", fqn) + } return nil, err } @@ -60,10 +63,10 @@ func (s *NetworksV1) Insert(ctx context.Context, req *pb.InsertNetworkRequest) ( id := s.generateID() obj := proto.Clone(req.GetNetworkResource()).(*pb.Network) - obj.SelfLink = PtrTo("https://compute.googleapis.com/compute/v1/" + name.String()) obj.CreationTimestamp = PtrTo(s.nowString()) obj.Id = &id - obj.SelfLinkWithId = PtrTo(fmt.Sprintf("https://compute.googleapis.com/compute/v1/projects/%s/global/networks/%d", name.Project.ID, id)) + obj.SelfLink = PtrTo("https://www.googleapis.com/compute/beta/" + name.String()) + obj.SelfLinkWithId = PtrTo(fmt.Sprintf("https://www.googleapis.com/compute/beta/projects/%s/global/networks/%d", name.Project.ID, id)) obj.Kind = PtrTo("compute#network") if err := s.storage.Create(ctx, fqn, obj); err != nil { @@ -72,8 +75,9 @@ func (s *NetworksV1) Insert(ctx context.Context, req *pb.InsertNetworkRequest) ( op := &pb.Operation{ TargetId: obj.Id, - TargetLink: obj.SelfLinkWithId, + TargetLink: obj.SelfLink, OperationType: PtrTo("insert"), + User: PtrTo("user@example.com"), } return s.startGlobalLRO(ctx, name.Project.ID, op, func() (proto.Message, error) { return obj, nil @@ -109,8 +113,9 @@ func (s *NetworksV1) Patch(ctx context.Context, req *pb.PatchNetworkRequest) (*p op := &pb.Operation{ TargetId: obj.Id, - TargetLink: obj.SelfLinkWithId, + TargetLink: obj.SelfLink, OperationType: PtrTo("compute.networks.patch"), + User: PtrTo("user@example.com"), } return s.startGlobalLRO(ctx, name.Project.ID, op, func() (proto.Message, error) { return obj, nil @@ -131,7 +136,10 @@ func (s *NetworksV1) Delete(ctx context.Context, req *pb.DeleteNetworkRequest) ( } op := &pb.Operation{ + TargetId: deleted.Id, + TargetLink: deleted.SelfLink, OperationType: PtrTo("delete"), + User: PtrTo("user@example.com"), } return s.startGlobalLRO(ctx, name.Project.ID, op, func() (proto.Message, error) { return deleted, nil diff --git a/mockgcp/mockcompute/operations.go b/mockgcp/mockcompute/operations.go index 863689f29b..b4a8e2a8a2 100644 --- a/mockgcp/mockcompute/operations.go +++ b/mockgcp/mockcompute/operations.go @@ -94,7 +94,7 @@ func (s *computeOperations) startLRO0(ctx context.Context, op *pb.Operation, fqn op.Progress = PtrTo(int32(0)) op.Kind = PtrTo("compute#operation") - op.SelfLink = PtrTo("https://compute.googleapis.com/compute/v1/" + fqn) + op.SelfLink = PtrTo("https://www.googleapis.com/compute/beta/" + fqn) op.Status = PtrTo(pb.Operation_RUNNING) diff --git a/mockgcp/mockcompute/service.go b/mockgcp/mockcompute/service.go index 3f59606d41..5d45f6f555 100644 --- a/mockgcp/mockcompute/service.go +++ b/mockgcp/mockcompute/service.go @@ -148,5 +148,11 @@ func (s *MockService) NewHTTPMux(ctx context.Context, conn *grpc.ClientConn) (ht return nil, err } + // Returns slightly non-standard errors + mux.RewriteError = func(ctx context.Context, error *httpmux.ErrorResponse) { + // Does not return status (at least for 404) + error.Status = "" + } + return mux, nil } diff --git a/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computenetwork/_generated_object_computenetwork.golden.yaml b/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computenetwork/_generated_object_computenetwork.golden.yaml index b0ecdf9d1d..556ff435dc 100644 --- a/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computenetwork/_generated_object_computenetwork.golden.yaml +++ b/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computenetwork/_generated_object_computenetwork.golden.yaml @@ -1,17 +1,3 @@ -# Copyright 2024 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. - apiVersion: compute.cnrm.cloud.google.com/v1beta1 kind: ComputeNetwork metadata: @@ -30,6 +16,7 @@ metadata: namespace: ${uniqueId} spec: autoCreateSubnetworks: false + enableUlaInternalIpv6: true networkFirewallPolicyEnforcementOrder: AFTER_CLASSIC_FIREWALL resourceID: computenetwork-${uniqueId} routingMode: GLOBAL @@ -41,4 +28,4 @@ status: status: "True" type: Ready observedGeneration: 3 - selfLink: https://compute.googleapis.com/compute/v1/projects/${projectId}/global/networks/computenetwork-${uniqueId} + selfLink: https://www.googleapis.com/compute/v1/projects/${projectId}/global/networks/computenetwork-${uniqueId} diff --git a/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computenetwork/_http.log b/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computenetwork/_http.log index 8f65372966..7c60bdb0d0 100644 --- a/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computenetwork/_http.log +++ b/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computenetwork/_http.log @@ -1,14 +1,30 @@ -GET https://compute.googleapis.com/compute/beta/projects/${projectId}/global/networks/computenetwork-${uniqueId}?alt=json +GET https://compute.googleapis.com/compute/beta/projects/${projectId}/global/networks/${networkID}?alt=json Content-Type: application/json User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager 404 Not Found -Content-Type: application/json +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 { - "code": 5, - "details": [], - "message": "network \"projects/${projectId}/global/networks/computenetwork-${uniqueId}\" not found" + "error": { + "code": 404, + "errors": [ + { + "domain": "global", + "message": "The resource 'projects/${projectId}/global/networks/computenetwork-${uniqueId}' was not found", + "reason": "notFound" + } + ], + "message": "The resource 'projects/${projectId}/global/networks/computenetwork-${uniqueId}' was not found" + } } --- @@ -27,59 +43,47 @@ User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 t } 200 OK -Content-Type: application/json -Grpc-Metadata-Content-Type: application/grpc +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 { "id": "000000000000000000000", - "insertTime": "2024-04-16T15:12:19-04:00", + "insertTime": "2024-04-01T12:34:56.123456Z", "kind": "compute#operation", "name": "${operationID}", "operationType": "insert", "progress": 0, - "selfLink": "https://compute.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID}", - "startTime": "2024-04-16T15:12:19-04:00", + "selfLink": "https://www.googleapis.com/compute/beta/projects/${projectId}/global/operations/${operationID}", + "startTime": "2024-04-01T12:34:56.123456Z", "status": "RUNNING", - "targetId": "1713294739430576901", - "targetLink": "https://compute.googleapis.com/compute/v1/projects/${projectId}/global/networks/1713294739430576901", - "warnings": [] -} - ---- - -GET https://compute.googleapis.com/compute/beta/projects/${projectId}/global/networks/computenetwork-${uniqueId}?alt=json -Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Content-Type: application/json -Grpc-Metadata-Content-Type: application/grpc - -{ - "autoCreateSubnetworks": false, - "creationTimestamp": "2024-04-01T12:34:56.123456Z", - "id": "000000000000000000000", - "kind": "compute#network", - "name": "computenetwork-${uniqueId}", - "networkFirewallPolicyEnforcementOrder": "AFTER_CLASSIC_FIREWALL", - "peerings": [], - "routingConfig": { - "routingMode": "REGIONAL" - }, - "selfLink": "https://compute.googleapis.com/compute/v1/projects/${projectId}/global/networks/computenetwork-${uniqueId}", - "selfLinkWithId": "https://compute.googleapis.com/compute/v1/projects/${projectId}/global/networks/1713294739430576901", - "subnetworks": [] + "targetId": "${networkID}", + "targetLink": "https://www.googleapis.com/compute/beta/projects/${projectId}/global/networks/computenetwork-${uniqueId}", + "user": "user@example.com" } --- -GET https://compute.googleapis.com/compute/beta/projects/${projectId}/global/networks/computenetwork-${uniqueId}?alt=json +GET https://compute.googleapis.com/compute/beta/projects/${projectId}/global/networks/${networkID}?alt=json Content-Type: application/json User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager 200 OK -Content-Type: application/json -Grpc-Metadata-Content-Type: application/grpc +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 { "autoCreateSubnetworks": false, @@ -88,44 +92,16 @@ Grpc-Metadata-Content-Type: application/grpc "kind": "compute#network", "name": "computenetwork-${uniqueId}", "networkFirewallPolicyEnforcementOrder": "AFTER_CLASSIC_FIREWALL", - "peerings": [], "routingConfig": { "routingMode": "REGIONAL" }, - "selfLink": "https://compute.googleapis.com/compute/v1/projects/${projectId}/global/networks/computenetwork-${uniqueId}", - "selfLinkWithId": "https://compute.googleapis.com/compute/v1/projects/${projectId}/global/networks/1713294739430576901", - "subnetworks": [] + "selfLink": "https://www.googleapis.com/compute/beta/projects/${projectId}/global/networks/computenetwork-${uniqueId}", + "selfLinkWithId": "https://www.googleapis.com/compute/beta/projects/${projectId}/global/networks/${networkID}" } --- -GET https://compute.googleapis.com/compute/beta/projects/${projectId}/global/networks/computenetwork-${uniqueId}?alt=json -Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Content-Type: application/json -Grpc-Metadata-Content-Type: application/grpc - -{ - "autoCreateSubnetworks": false, - "creationTimestamp": "2024-04-01T12:34:56.123456Z", - "id": "000000000000000000000", - "kind": "compute#network", - "name": "computenetwork-${uniqueId}", - "networkFirewallPolicyEnforcementOrder": "AFTER_CLASSIC_FIREWALL", - "peerings": [], - "routingConfig": { - "routingMode": "REGIONAL" - }, - "selfLink": "https://compute.googleapis.com/compute/v1/projects/${projectId}/global/networks/computenetwork-${uniqueId}", - "selfLinkWithId": "https://compute.googleapis.com/compute/v1/projects/${projectId}/global/networks/1713294739430576901", - "subnetworks": [] -} - ---- - -PATCH https://compute.googleapis.com/compute/beta/projects/${projectId}/global/networks/computenetwork-${uniqueId}?alt=json +PATCH https://compute.googleapis.com/compute/beta/projects/${projectId}/global/networks/${networkID}?alt=json Content-Type: application/json User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager @@ -137,33 +113,47 @@ User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 t } 200 OK -Content-Type: application/json -Grpc-Metadata-Content-Type: application/grpc +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 { "id": "000000000000000000000", - "insertTime": "2024-04-16T15:12:19-04:00", + "insertTime": "2024-04-01T12:34:56.123456Z", "kind": "compute#operation", "name": "${operationID}", "operationType": "compute.networks.patch", "progress": 0, - "selfLink": "https://compute.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID}", - "startTime": "2024-04-16T15:12:19-04:00", + "selfLink": "https://www.googleapis.com/compute/beta/projects/${projectId}/global/operations/${operationID}", + "startTime": "2024-04-01T12:34:56.123456Z", "status": "RUNNING", - "targetId": "1713294739430576901", - "targetLink": "https://compute.googleapis.com/compute/v1/projects/${projectId}/global/networks/1713294739430576901", - "warnings": [] + "targetId": "${networkID}", + "targetLink": "https://www.googleapis.com/compute/beta/projects/${projectId}/global/networks/computenetwork-${uniqueId}", + "user": "user@example.com" } --- -GET https://compute.googleapis.com/compute/beta/projects/${projectId}/global/networks/computenetwork-${uniqueId}?alt=json +GET https://compute.googleapis.com/compute/beta/projects/${projectId}/global/networks/${networkID}?alt=json Content-Type: application/json User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager 200 OK -Content-Type: application/json -Grpc-Metadata-Content-Type: application/grpc +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 { "autoCreateSubnetworks": false, @@ -172,60 +162,41 @@ Grpc-Metadata-Content-Type: application/grpc "kind": "compute#network", "name": "computenetwork-${uniqueId}", "networkFirewallPolicyEnforcementOrder": "AFTER_CLASSIC_FIREWALL", - "peerings": [], "routingConfig": { "routingMode": "GLOBAL" }, - "selfLink": "https://compute.googleapis.com/compute/v1/projects/${projectId}/global/networks/computenetwork-${uniqueId}", - "selfLinkWithId": "https://compute.googleapis.com/compute/v1/projects/${projectId}/global/networks/1713294739430576901", - "subnetworks": [] + "selfLink": "https://www.googleapis.com/compute/beta/projects/${projectId}/global/networks/computenetwork-${uniqueId}", + "selfLinkWithId": "https://www.googleapis.com/compute/beta/projects/${projectId}/global/networks/${networkID}" } --- -GET https://compute.googleapis.com/compute/beta/projects/${projectId}/global/networks/computenetwork-${uniqueId}?alt=json +DELETE https://compute.googleapis.com/compute/beta/projects/${projectId}/global/networks/${networkID}?alt=json Content-Type: application/json User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager 200 OK -Content-Type: application/json -Grpc-Metadata-Content-Type: application/grpc - -{ - "autoCreateSubnetworks": false, - "creationTimestamp": "2024-04-01T12:34:56.123456Z", - "id": "000000000000000000000", - "kind": "compute#network", - "name": "computenetwork-${uniqueId}", - "networkFirewallPolicyEnforcementOrder": "AFTER_CLASSIC_FIREWALL", - "peerings": [], - "routingConfig": { - "routingMode": "GLOBAL" - }, - "selfLink": "https://compute.googleapis.com/compute/v1/projects/${projectId}/global/networks/computenetwork-${uniqueId}", - "selfLinkWithId": "https://compute.googleapis.com/compute/v1/projects/${projectId}/global/networks/1713294739430576901", - "subnetworks": [] -} - ---- - -DELETE https://compute.googleapis.com/compute/beta/projects/${projectId}/global/networks/computenetwork-${uniqueId}?alt=json -Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Content-Type: application/json -Grpc-Metadata-Content-Type: application/grpc +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 { "id": "000000000000000000000", - "insertTime": "2024-04-16T15:12:20-04:00", + "insertTime": "2024-04-01T12:34:56.123456Z", "kind": "compute#operation", "name": "${operationID}", "operationType": "delete", "progress": 0, - "selfLink": "https://compute.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID}", - "startTime": "2024-04-16T15:12:20-04:00", + "selfLink": "https://www.googleapis.com/compute/beta/projects/${projectId}/global/operations/${operationID}", + "startTime": "2024-04-01T12:34:56.123456Z", "status": "RUNNING", - "warnings": [] + "targetId": "${networkID}", + "targetLink": "https://www.googleapis.com/compute/beta/projects/${projectId}/global/networks/computenetwork-${uniqueId}", + "user": "user@example.com" } \ No newline at end of file diff --git a/tests/e2e/normalize.go b/tests/e2e/normalize.go index b86cd06c49..09efb3c126 100644 --- a/tests/e2e/normalize.go +++ b/tests/e2e/normalize.go @@ -30,7 +30,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" ) -func normalizeObject(u *unstructured.Unstructured, project testgcp.GCPProject, uniqueID string) error { +func normalizeKRMObject(u *unstructured.Unstructured, project testgcp.GCPProject, uniqueID string) error { annotations := u.GetAnnotations() if annotations["cnrm.cloud.google.com/observed-secret-versions"] != "" { // Includes resource versions, very volatile @@ -302,12 +302,29 @@ func NormalizeHTTPLog(t *testing.T, events test.LogEntries, project testgcp.GCPP } } + normalizeHTTPResponses(t, events) + + // Normalize using the KRM normalization function events.PrettifyJSON(func(obj map[string]any) { u := &unstructured.Unstructured{} u.Object = obj - if err := normalizeObject(u, project, uniqueID); err != nil { + if err := normalizeKRMObject(u, project, uniqueID); err != nil { t.Fatalf("error from normalizeObject: %v", err) } }) +} + +func normalizeHTTPResponses(t *testing.T, events test.LogEntries) { + visitor := objectWalker{} + + visitor.removePaths = sets.New[string]() + + // If we get detailed info, don't record it - it's not part of the API contract + visitor.removePaths.Insert(".error.errors[].debugInfo") + events.PrettifyJSON(func(obj map[string]any) { + if err := visitor.visitMap(obj, ""); err != nil { + t.Fatalf("error normalizing response: %v", err) + } + }) } diff --git a/tests/e2e/script_test.go b/tests/e2e/script_test.go index d1c3559250..5826a538a9 100644 --- a/tests/e2e/script_test.go +++ b/tests/e2e/script_test.go @@ -217,7 +217,7 @@ func TestE2EScript(t *testing.T) { t.Logf("ignoring failure to export resource of gvk %v", exportResource.GroupVersionKind()) // t.Errorf("failed to export resource of gvk %v", exportResource.GroupVersionKind()) } else { - if err := normalizeObject(u, project, uniqueID); err != nil { + if err := normalizeKRMObject(u, project, uniqueID); err != nil { t.Fatalf("error from normalizeObject: %v", err) } got, err := yaml.Marshal(u) @@ -240,7 +240,7 @@ func TestE2EScript(t *testing.T) { if err := h.GetClient().Get(ctx, id, u); err != nil { t.Errorf("failed to get kube object: %v", err) } else { - if err := normalizeObject(u, project, uniqueID); err != nil { + if err := normalizeKRMObject(u, project, uniqueID); err != nil { t.Fatalf("error from normalizeObject: %v", err) } got, err := yaml.Marshal(u) diff --git a/tests/e2e/unified_test.go b/tests/e2e/unified_test.go index 001cbeeab9..d900cd348a 100644 --- a/tests/e2e/unified_test.go +++ b/tests/e2e/unified_test.go @@ -270,7 +270,7 @@ func runScenario(ctx context.Context, t *testing.T, testPause bool, fixture reso if err := yaml.Unmarshal([]byte(exportedYAML), exportedObj); err != nil { t.Fatalf("error from yaml.Unmarshal: %v", err) } - if err := normalizeObject(exportedObj, project, uniqueID); err != nil { + if err := normalizeKRMObject(exportedObj, project, uniqueID); err != nil { t.Fatalf("error from normalizeObject: %v", err) } got, err := yaml.Marshal(exportedObj) @@ -288,7 +288,7 @@ func runScenario(ctx context.Context, t *testing.T, testPause bool, fixture reso if err := h.GetClient().Get(ctx, id, u); err != nil { t.Errorf("failed to get KRM object: %v", err) } else { - if err := normalizeObject(u, project, uniqueID); err != nil { + if err := normalizeKRMObject(u, project, uniqueID); err != nil { t.Fatalf("error from normalizeObject: %v", err) } got, err := yaml.Marshal(u) @@ -339,6 +339,8 @@ func runScenario(ctx context.Context, t *testing.T, testPause bool, fixture reso pathIDs[id] = "${tagValueID}" case "datasets": pathIDs[id] = "${datasetID}" + case "networks": + pathIDs[id] = "${networkID}" case "notificationChannels": pathIDs[id] = "${notificationChannelID}" case "alertPolicies": @@ -387,13 +389,8 @@ func runScenario(ctx context.Context, t *testing.T, testPause bool, fixture reso for _, event := range events { body := event.Response.ParseBody() - if val, ok := body["selfLinkWithId"]; ok { - s := val.(string) - // self link name format: {prefix}/networks/{networksId} - if ix := strings.Index(s, "/networks/"); ix != -1 { - id := strings.TrimPrefix(s[ix:], "/networks/") - networkIDs[id] = true - } + if selfLinkWithId, _, _ := unstructured.NestedString(body, "selfLinkWithId"); selfLinkWithId != "" { + extractIDsFromLinks(selfLinkWithId) } if conditions, _, _ := unstructured.NestedSlice(body, "conditions"); conditions != nil { @@ -510,6 +507,11 @@ func runScenario(ctx context.Context, t *testing.T, testPause bool, fixture reso addReplacement("reservedIpRange", "10.1.2.0/24") addReplacement("metadata.endTime", "2024-04-01T12:34:56.123456Z") + // For compute operations + addReplacement("insertTime", "2024-04-01T12:34:56.123456Z") + addReplacement("startTime", "2024-04-01T12:34:56.123456Z") + addReplacement("user", "user@example.com") + // Specific to vertexai addReplacement("blobStoragePathPrefix", "cloud-ai-platform-00000000-1111-2222-3333-444444444444") addReplacement("response.blobStoragePathPrefix", "cloud-ai-platform-00000000-1111-2222-3333-444444444444")