diff --git a/apis/refs/v1beta1/computerefs.go b/apis/refs/v1beta1/computerefs.go index a491f5fca0..a35511c130 100644 --- a/apis/refs/v1beta1/computerefs.go +++ b/apis/refs/v1beta1/computerefs.go @@ -17,8 +17,11 @@ package v1beta1 import ( "context" "fmt" + "strconv" "strings" + resourcemanager "cloud.google.com/go/resourcemanager/apiv3" + resourcemanagerpb "cloud.google.com/go/resourcemanager/apiv3/resourcemanagerpb" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -44,61 +47,87 @@ type ComputeNetworkRef struct { Name string `json:"name,omitempty"` /* The `namespace` field of a `ComputeNetwork` resource. */ Namespace string `json:"namespace,omitempty"` - - ProjectNumber string `json:"-"` -} - -func (networkRef *ComputeNetworkRef) WithProjectNumber() string { - _, id, _ := ParseComputeNetworkExternal(networkRef.External) - return buildNetworkExternal(networkRef.ProjectNumber, id) -} - -type ComputeNetwork struct { - Project string - ComputeNetworkID string } -func (c *ComputeNetwork) String() string { - return buildNetworkExternal(c.Project, c.ComputeNetworkID) +type ComputeNetworkID struct { + Project string + Network string } -func buildNetworkExternal(project, network string) string { - return fmt.Sprintf("projects/%s/global/networks/%s", project, network) +func (c *ComputeNetworkID) String() string { + return fmt.Sprintf("projects/%s/global/networks/%s", c.Project, c.Network) } -func ParseComputeNetworkExternal(external string) (string, string, error) { +func ParseComputeNetworkID(external string) (*ComputeNetworkID, error) { if external == "" { - return "", "", fmt.Errorf("parse empty ComputeNetwork external value") + return nil, fmt.Errorf("empty ComputeNetwork external value") } external = fixStaleExternalFormat(external) tokens := strings.Split(external, "/") if len(tokens) == 5 && tokens[0] == "projects" && tokens[2] == "global" && tokens[3] == "networks" { - return tokens[1], tokens[4], nil + return &ComputeNetworkID{ + Project: tokens[1], + Network: tokens[4], + }, nil } - return "", "", fmt.Errorf("format of computenetwork external=%q was not known (use projects//global/networks/)", external) + return nil, fmt.Errorf("format of computenetwork external=%q was not known (use projects//global/networks/)", external) } -func ResolveComputeNetwork(ctx context.Context, reader client.Reader, src client.Object, ref *ComputeNetworkRef) (*ComputeNetwork, error) { +// ConvertToProjectNumber converts the external reference to use a project number. +func (ref *ComputeNetworkRef) ConvertToProjectNumber(ctx context.Context, projectsClient *resourcemanager.ProjectsClient) error { if ref == nil { - return nil, nil + return nil + } + + id, err := ParseComputeNetworkID(ref.External) + if err != nil { + return err + } + + // Check if the project number is already a valid integer + // If not, we need to look it up + projectNumber, err := strconv.ParseInt(id.Project, 10, 64) + if err != nil { + req := &resourcemanagerpb.GetProjectRequest{ + Name: "projects/" + id.Project, + } + project, err := projectsClient.GetProject(ctx, req) + if err != nil { + return fmt.Errorf("error getting project %q: %w", req.Name, err) + } + n, err := strconv.ParseInt(strings.TrimPrefix(project.Name, "projects/"), 10, 64) + if err != nil { + return fmt.Errorf("error parsing project number for %q: %w", project.Name, err) + } + projectNumber = n + } + id.Project = strconv.FormatInt(projectNumber, 10) + ref.External = id.String() + return nil +} + +func (ref *ComputeNetworkRef) Normalize(ctx context.Context, reader client.Reader, src client.Object) error { + if ref == nil { + return nil } if ref.External != "" && ref.Name != "" { - return nil, fmt.Errorf("cannot specify both name and external on computenetwork reference") + return fmt.Errorf("cannot specify both name and external on computenetwork reference") } if ref.External != "" { - project, networkID, err := ParseComputeNetworkExternal(ref.External) + id, err := ParseComputeNetworkID(ref.External) if err != nil { - return nil, err + return err + } + *ref = ComputeNetworkRef{ + External: id.String(), } - return &ComputeNetwork{ - Project: project, - ComputeNetworkID: networkID}, nil + return nil } if ref.Name == "" { - return nil, fmt.Errorf("must specify either name or external on computenetwork reference") + return fmt.Errorf("must specify either name or external on computenetwork reference") } key := types.NamespacedName{ @@ -109,32 +138,37 @@ func ResolveComputeNetwork(ctx context.Context, reader client.Reader, src client key.Namespace = src.GetNamespace() } - computenetwork := &unstructured.Unstructured{} - computenetwork.SetGroupVersionKind(schema.GroupVersionKind{ + computeNetwork := &unstructured.Unstructured{} + computeNetwork.SetGroupVersionKind(schema.GroupVersionKind{ Group: "compute.cnrm.cloud.google.com", Version: "v1beta1", Kind: "ComputeNetwork", }) - if err := reader.Get(ctx, key, computenetwork); err != nil { + if err := reader.Get(ctx, key, computeNetwork); err != nil { if apierrors.IsNotFound(err) { - return nil, k8s.NewReferenceNotFoundError(computenetwork.GroupVersionKind(), key) + return k8s.NewReferenceNotFoundError(computeNetwork.GroupVersionKind(), key) } - return nil, fmt.Errorf("error reading referenced ComputeNetwork %v: %w", key, err) + return fmt.Errorf("error reading referenced ComputeNetwork %v: %w", key, err) } - computenetworkID, err := GetResourceID(computenetwork) + resourceID, err := GetResourceID(computeNetwork) if err != nil { - return nil, err + return err } - computeNetworkProjectID, err := ResolveProjectID(ctx, reader, computenetwork) + projectID, err := ResolveProjectID(ctx, reader, computeNetwork) if err != nil { - return nil, err + return err } - return &ComputeNetwork{ - Project: computeNetworkProjectID, - ComputeNetworkID: computenetworkID, - }, nil + + id := ComputeNetworkID{ + Project: projectID, + Network: resourceID, + } + *ref = ComputeNetworkRef{ + External: id.String(), + } + return nil } type ComputeSubnetworkRef struct { diff --git a/mockgcp/mockcloudbuild/workerpool.go b/mockgcp/mockcloudbuild/workerpool.go index 229aead545..fefd892740 100644 --- a/mockgcp/mockcloudbuild/workerpool.go +++ b/mockgcp/mockcloudbuild/workerpool.go @@ -16,6 +16,7 @@ package mockcloudbuild import ( "context" + "fmt" "strconv" "strings" @@ -67,6 +68,11 @@ func (s *CloudBuildV1) CreateWorkerPool(ctx context.Context, req *pb.CreateWorke obj.CreateTime = now populateDefaultsForWorkerPool(obj) + + if err := s.validateAndNormalizeWorkerPool(obj); err != nil { + return nil, err + } + if err := s.storage.Create(ctx, fqn, obj); err != nil { return nil, err } @@ -81,19 +87,40 @@ func (s *CloudBuildV1) CreateWorkerPool(ctx context.Context, req *pb.CreateWorke func populateDefaultsForWorkerPool(wp *pb.WorkerPool) { now := timestamppb.Now() - network := wp.GetPrivatePoolV1Config().GetNetworkConfig() - if network != nil { - tokens := strings.Split(network.PeeredNetwork, "/") - if len(tokens) == 5 { - network.PeeredNetwork = tokens[0] + "/" + "${projectNumber}" + "/" + tokens[2] + "/" + tokens[3] + "/" + tokens[4] - } - } wp.UpdateTime = now wp.State = pb.WorkerPool_RUNNING wp.Etag = fields.ComputeWeakEtag(wp) wp.Uid = "11111111111111111111" } +func (s *CloudBuildV1) validateAndNormalizeWorkerPool(wp *pb.WorkerPool) error { + privatePoolV1Config := wp.GetPrivatePoolV1Config() + + // Normalize the peered network link to always use the project number + if privatePoolV1Config != nil && privatePoolV1Config.NetworkConfig != nil { + peeredNetwork := privatePoolV1Config.NetworkConfig.GetPeeredNetwork() + if peeredNetwork == "" { + return status.Errorf(codes.InvalidArgument, "peeredNetwork is required") + } else { + tokens := strings.Split(peeredNetwork, "/") + projectToken := "" + if len(tokens) == 5 && tokens[0] == "projects" && tokens[2] == "global" && tokens[3] == "networks" { + projectToken = tokens[1] + } else { + return fmt.Errorf("format of peered network %q was not known (use projects//global/networks/)", peeredNetwork) + } + + project, err := s.Projects.GetProjectByIDOrNumber(projectToken) + if err != nil { + return fmt.Errorf("error getting project %q: %w", projectToken, err) + } + + privatePoolV1Config.NetworkConfig.PeeredNetwork = fmt.Sprintf("projects/%d/global/networks/%s", project.Number, tokens[4]) + } + } + return nil +} + func (s *CloudBuildV1) UpdateWorkerPool(ctx context.Context, req *pb.UpdateWorkerPoolRequest) (*longrunningpb.Operation, error) { name, err := s.parseWorkerPoolName(req.WorkerPool.Name) if err != nil { @@ -111,7 +138,13 @@ func (s *CloudBuildV1) UpdateWorkerPool(ctx context.Context, req *pb.UpdateWorke if err := fields.UpdateByFieldMask(obj, req.WorkerPool, req.UpdateMask.Paths); err != nil { return nil, err } + populateDefaultsForWorkerPool(obj) + + if err := s.validateAndNormalizeWorkerPool(obj); err != nil { + return nil, err + } + if err := s.storage.Update(ctx, fqn, obj); err != nil { return nil, err } diff --git a/pkg/controller/direct/cloudbuild/workerpool_controller.go b/pkg/controller/direct/cloudbuild/workerpool_controller.go index e682d9fa42..77c457dc1e 100644 --- a/pkg/controller/direct/cloudbuild/workerpool_controller.go +++ b/pkg/controller/direct/cloudbuild/workerpool_controller.go @@ -23,6 +23,7 @@ import ( gcp "cloud.google.com/go/cloudbuild/apiv1/v2" cloudbuildpb "cloud.google.com/go/cloudbuild/apiv1/v2/cloudbuildpb" + cloudresourcemanager "cloud.google.com/go/resourcemanager/apiv3" "google.golang.org/protobuf/types/known/fieldmaskpb" krm "github.com/GoogleCloudPlatform/k8s-config-connector/apis/cloudbuild/v1beta1" @@ -68,6 +69,19 @@ func (m *model) client(ctx context.Context) (*gcp.Client, error) { return gcpClient, err } +func (m *model) projectsClient(ctx context.Context) (*cloudresourcemanager.ProjectsClient, error) { + opts, err := m.config.RESTClientOptions() + if err != nil { + return nil, err + } + + crmClient, err := cloudresourcemanager.NewProjectsRESTClient(ctx, opts...) + if err != nil { + return nil, fmt.Errorf("building cloudresourcemanager client: %w", err) + } + return crmClient, err +} + func (m *model) AdapterForObject(ctx context.Context, reader client.Reader, u *unstructured.Unstructured) (directbase.Adapter, error) { obj := &krm.CloudBuildWorkerPool{} if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, &obj); err != nil { @@ -123,21 +137,17 @@ func (m *model) AdapterForObject(ctx context.Context, reader client.Reader, u *u // Get computeNetwork networkSpec := obj.Spec.PrivatePoolConfig.NetworkConfig if networkSpec != nil { - peeredNetworkRef, err := refs.ResolveComputeNetwork(ctx, reader, obj, &networkSpec.PeeredNetworkRef) - if err != nil { + if err := networkSpec.PeeredNetworkRef.Normalize(ctx, reader, obj); err != nil { return nil, err + } + projectsClient, err := m.projectsClient(ctx) + if err != nil { + return nil, err } - obj.Spec.PrivatePoolConfig.NetworkConfig.PeeredNetworkRef.External = peeredNetworkRef.String() - if obj.Status.ObservedState != nil { - fromStatus := obj.Status.ObservedState.NetworkConfig.PeeredNetwork - if fromStatus != nil { - projectNumber, _, err := refs.ParseComputeNetworkExternal(*fromStatus) - if err != nil { - return nil, err - } - networkSpec.PeeredNetworkRef.ProjectNumber = projectNumber - } + + if err := networkSpec.PeeredNetworkRef.ConvertToProjectNumber(ctx, projectsClient); err != nil { + return nil, err } } @@ -252,15 +262,8 @@ func (a *Adapter) Update(ctx context.Context, updateOp *directbase.UpdateOperati } wp.Name = a.id.FullyQualifiedName() wp.Etag = a.actual.Etag - // the peered_network has a different HTTP request and response format. - // The HTTP request uses ProjectID, in the form of /projects//global/networks/ - // The HTTP response uses ProjectNumber, in the form of /projects//global/networks/ - // When comparing the desired and actual fields, we need to align the project format, to avoid updating the - // "peered_network" field. - // Why we can't just update the "peered_network" field? Because it is immutable. ¯\_(ツ)_/¯ - wp.GetPrivatePoolV1Config().NetworkConfig.PeeredNetwork = desired.Spec.PrivatePoolConfig.NetworkConfig.PeeredNetworkRef.WithProjectNumber() - paths, err := common.CompareProtoMessage(wp, a.actual, common.BasicDiff) + paths, err := common.CompareProtoMessage(wp, a.actual, common.BasicDiff) if err != nil { return err } diff --git a/pkg/controller/direct/dataflow/refs.go b/pkg/controller/direct/dataflow/refs.go index 20c63e7ec1..d114da1492 100644 --- a/pkg/controller/direct/dataflow/refs.go +++ b/pkg/controller/direct/dataflow/refs.go @@ -53,13 +53,9 @@ func (r *refNormalizer) VisitField(path string, v any) error { } if networkRef, ok := v.(*refs.ComputeNetworkRef); ok { - resolved, err := refs.ResolveComputeNetwork(r.ctx, r.kube, r.src, networkRef) - if err != nil { + if err := networkRef.Normalize(r.ctx, r.kube, r.src); err != nil { return err } - *networkRef = refs.ComputeNetworkRef{ - External: resolved.String(), - } } if subnetworkRef, ok := v.(*refs.ComputeSubnetworkRef); ok { diff --git a/pkg/controller/direct/networkconnectivity/refs.go b/pkg/controller/direct/networkconnectivity/refs.go index 72def3c586..c13046522b 100644 --- a/pkg/controller/direct/networkconnectivity/refs.go +++ b/pkg/controller/direct/networkconnectivity/refs.go @@ -53,13 +53,9 @@ func (r *refNormalizer) VisitField(path string, v any) error { } if networkRef, ok := v.(*refs.ComputeNetworkRef); ok { - resolved, err := refs.ResolveComputeNetwork(r.ctx, r.kube, r.src, networkRef) - if err != nil { + if err := networkRef.Normalize(r.ctx, r.kube, r.src); err != nil { return err } - *networkRef = refs.ComputeNetworkRef{ - External: resolved.String(), - } } if subnetworkRef, ok := v.(*refs.ComputeSubnetworkRef); ok { diff --git a/pkg/controller/direct/redis/cluster/refs.go b/pkg/controller/direct/redis/cluster/refs.go index c5476f808a..65a18c6025 100644 --- a/pkg/controller/direct/redis/cluster/refs.go +++ b/pkg/controller/direct/redis/cluster/refs.go @@ -53,13 +53,9 @@ func (r *refNormalizer) VisitField(path string, v any) error { } if networkRef, ok := v.(*refs.ComputeNetworkRef); ok { - resolved, err := refs.ResolveComputeNetwork(r.ctx, r.kube, r.src, networkRef) - if err != nil { + if err := networkRef.Normalize(r.ctx, r.kube, r.src); err != nil { return err } - *networkRef = refs.ComputeNetworkRef{ - External: resolved.String(), - } } return nil diff --git a/pkg/controller/direct/sql/sqlinstance_resolverefs.go b/pkg/controller/direct/sql/sqlinstance_resolverefs.go index 51fbdce39a..2acd718273 100644 --- a/pkg/controller/direct/sql/sqlinstance_resolverefs.go +++ b/pkg/controller/direct/sql/sqlinstance_resolverefs.go @@ -228,12 +228,11 @@ func resolvePrivateNetworkRef(ctx context.Context, kube client.Reader, obj *krm. Name: resRef.Name, Namespace: resRef.Namespace, } - net, err := refs.ResolveComputeNetwork(ctx, kube, obj, netRef) - if err != nil { + if err := netRef.Normalize(ctx, kube, obj); err != nil { return err } - obj.Spec.Settings.IpConfiguration.PrivateNetworkRef.External = net.String() + obj.Spec.Settings.IpConfiguration.PrivateNetworkRef.External = netRef.External return nil } diff --git a/pkg/controller/direct/workstations/workstationcluster_normalize.go b/pkg/controller/direct/workstations/workstationcluster_normalize.go index 654b2eb19c..087e2d1a64 100644 --- a/pkg/controller/direct/workstations/workstationcluster_normalize.go +++ b/pkg/controller/direct/workstations/workstationcluster_normalize.go @@ -25,11 +25,9 @@ import ( func NormalizeWorkstationCluster(ctx context.Context, kube client.Reader, obj *krm.WorkstationCluster) error { // Resolve network. - network, err := refs.ResolveComputeNetwork(ctx, kube, obj, &obj.Spec.NetworkRef) - if err != nil { + if err := obj.Spec.NetworkRef.Normalize(ctx, kube, obj); err != nil { return err } - obj.Spec.NetworkRef.External = network.String() // Resolve subnetwork. subnet, err := refs.ResolveComputeSubnetwork(ctx, kube, obj, &obj.Spec.SubnetworkRef) diff --git a/pkg/test/resourcefixture/testdata/basic/cloudbuild/v1beta1/cloudbuildworkerpool/_http.log b/pkg/test/resourcefixture/testdata/basic/cloudbuild/v1beta1/cloudbuildworkerpool/_http.log index 08aa1402f0..c6ec1b9cbf 100644 --- a/pkg/test/resourcefixture/testdata/basic/cloudbuild/v1beta1/cloudbuildworkerpool/_http.log +++ b/pkg/test/resourcefixture/testdata/basic/cloudbuild/v1beta1/cloudbuildworkerpool/_http.log @@ -582,6 +582,32 @@ X-Xss-Protection: 0 --- +GET https://cloudresourcemanager.googleapis.com/v3/projects/${projectId}?%24alt=json%3Benum-encoding%3Dint +Content-Type: application/json +User-Agent: kcc/controller-manager +x-goog-request-params: name=projects%2F${projectId} + +200 OK +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 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "etag": "abcdef0123A=", + "name": "projects/${projectNumber}", + "projectId": "${projectId}", + "state": 1 +} + +--- + GET https://cloudbuild.googleapis.com/v1/projects/${projectId}/locations/us-central1/workerPools/cloudbuildworkerpool-${uniqueId}?%24alt=json%3Benum-encoding%3Dint Content-Type: application/json User-Agent: kcc/controller-manager @@ -619,7 +645,7 @@ x-goog-request-params: location=us-central1 "privatePoolV1Config": { "networkConfig": { "egressOption": 1, - "peeredNetwork": "projects/${projectId}/global/networks/computenetwork-${uniqueId}", + "peeredNetwork": "projects/${projectNumber}/global/networks/computenetwork-${uniqueId}", "peeredNetworkIpRange": "/29" }, "workerConfig": { @@ -700,6 +726,32 @@ X-Xss-Protection: 0 --- +GET https://cloudresourcemanager.googleapis.com/v3/projects/${projectId}?%24alt=json%3Benum-encoding%3Dint +Content-Type: application/json +User-Agent: kcc/controller-manager +x-goog-request-params: name=projects%2F${projectId} + +200 OK +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 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "etag": "abcdef0123A=", + "name": "projects/${projectNumber}", + "projectId": "${projectId}", + "state": 1 +} + +--- + GET https://cloudbuild.googleapis.com/v1/projects/${projectId}/locations/us-central1/workerPools/cloudbuildworkerpool-${uniqueId}?%24alt=json%3Benum-encoding%3Dint Content-Type: application/json User-Agent: kcc/controller-manager @@ -871,6 +923,136 @@ X-Xss-Protection: 0 --- +GET https://cloudresourcemanager.googleapis.com/v3/projects/${projectId}?%24alt=json%3Benum-encoding%3Dint +Content-Type: application/json +User-Agent: kcc/controller-manager +x-goog-request-params: name=projects%2F${projectId} + +200 OK +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 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "etag": "abcdef0123A=", + "name": "projects/${projectNumber}", + "projectId": "${projectId}", + "state": 1 +} + +--- + +GET https://cloudbuild.googleapis.com/v1/projects/${projectId}/locations/us-central1/workerPools/cloudbuildworkerpool-${uniqueId}?%24alt=json%3Benum-encoding%3Dint +Content-Type: application/json +User-Agent: kcc/controller-manager +x-goog-request-params: location=us-central1 + +200 OK +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 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "displayName": "Updated CloudBuild WorkerPool", + "etag": "abcdef0123A=", + "name": "projects/${projectNumber}/locations/us-central1/workerPools/cloudbuildworkerpool-${uniqueId}", + "privatePoolV1Config": { + "networkConfig": { + "egressOption": 2, + "peeredNetwork": "projects/${projectNumber}/global/networks/computenetwork-${uniqueId}", + "peeredNetworkIpRange": "/29" + }, + "workerConfig": { + "diskSizeGb": "150", + "machineType": "e2-highmem-4" + } + }, + "state": 2, + "uid": "111111111111111111111", + "updateTime": "2024-04-01T12:34:56.123456Z" +} + +--- + +GET https://cloudresourcemanager.googleapis.com/v3/projects/${projectId}?%24alt=json%3Benum-encoding%3Dint +Content-Type: application/json +User-Agent: kcc/controller-manager +x-goog-request-params: name=projects%2F${projectId} + +200 OK +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 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "etag": "abcdef0123A=", + "name": "projects/${projectNumber}", + "projectId": "${projectId}", + "state": 1 +} + +--- + +GET https://cloudbuild.googleapis.com/v1/projects/${projectId}/locations/us-central1/workerPools/cloudbuildworkerpool-${uniqueId}?%24alt=json%3Benum-encoding%3Dint +Content-Type: application/json +User-Agent: kcc/controller-manager +x-goog-request-params: location=us-central1 + +200 OK +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 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "displayName": "Updated CloudBuild WorkerPool", + "etag": "abcdef0123A=", + "name": "projects/${projectNumber}/locations/us-central1/workerPools/cloudbuildworkerpool-${uniqueId}", + "privatePoolV1Config": { + "networkConfig": { + "egressOption": 2, + "peeredNetwork": "projects/${projectNumber}/global/networks/computenetwork-${uniqueId}", + "peeredNetworkIpRange": "/29" + }, + "workerConfig": { + "diskSizeGb": "150", + "machineType": "e2-highmem-4" + } + }, + "state": 2, + "uid": "111111111111111111111", + "updateTime": "2024-04-01T12:34:56.123456Z" +} + +--- + DELETE https://cloudbuild.googleapis.com/v1/projects/${projectId}/locations/us-central1/workerPools/cloudbuildworkerpool-${uniqueId}?%24alt=json%3Benum-encoding%3Dint&allowMissing=true Content-Type: application/json User-Agent: kcc/controller-manager