diff --git a/hack/compare-mock b/hack/compare-mock index 268920d4ab9..69aa18db924 100755 --- a/hack/compare-mock +++ b/hack/compare-mock @@ -16,6 +16,6 @@ E2E_GCP_TARGET=mock \ GOLDEN_REQUEST_CHECKS=1 \ GOLDEN_OBJECT_CHECKS=1 \ WRITE_GOLDEN_OUTPUT=1 \ -KCC_USE_DIRECT_RECONCILERS="SQLInstance" \ +KCC_USE_DIRECT_RECONCILERS="SQLInstance,ComputeForwardingRule" \ RUN_E2E=1 \ go test ./tests/e2e -timeout 3600s -v -run $RUN_TESTS \ No newline at end of file diff --git a/pkg/controller/direct/compute/client.go b/pkg/controller/direct/compute/client.go new file mode 100644 index 00000000000..51eae5e28b9 --- /dev/null +++ b/pkg/controller/direct/compute/client.go @@ -0,0 +1,101 @@ +// 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. + +package compute + +import ( + "context" + "fmt" + "net/http" + + api "cloud.google.com/go/compute/apiv1" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/config" + "google.golang.org/api/option" +) + +type gcpClient struct { + config config.ControllerConfig +} + +func newGCPClient(ctx context.Context, config *config.ControllerConfig) (*gcpClient, error) { + gcpClient := &gcpClient{ + config: *config, + } + return gcpClient, nil +} + +func (m *gcpClient) options() ([]option.ClientOption, error) { + var opts []option.ClientOption + if m.config.UserAgent != "" { + opts = append(opts, option.WithUserAgent(m.config.UserAgent)) + } + if m.config.HTTPClient != nil { + // TODO: Set UserAgent in this scenario (error is: WithHTTPClient is incompatible with gRPC dial options) + + httpClient := &http.Client{} + *httpClient = *m.config.HTTPClient + httpClient.Transport = &optionsRoundTripper{ + config: m.config, + inner: m.config.HTTPClient.Transport, + } + opts = append(opts, option.WithHTTPClient(httpClient)) + } + if m.config.UserProjectOverride && m.config.BillingProject != "" { + opts = append(opts, option.WithQuotaProject(m.config.BillingProject)) + } + + // TODO: support endpoints? + // if m.config.Endpoint != "" { + // opts = append(opts, option.WithEndpoint(m.config.Endpoint)) + // } + + return opts, nil +} + +type optionsRoundTripper struct { + config config.ControllerConfig + inner http.RoundTripper +} + +func (m *optionsRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + if m.config.UserAgent != "" { + req.Header.Set("User-Agent", m.config.UserAgent) + req.Header.Del("x-goog-request-params") + } + return m.inner.RoundTrip(req) +} + +func (m *gcpClient) globalForwardingRuleClient(ctx context.Context) (*api.GlobalForwardingRulesClient, error) { + opts, err := m.options() + if err != nil { + return nil, err + } + client, err := api.NewGlobalForwardingRulesRESTClient(ctx, opts...) + if err != nil { + return nil, fmt.Errorf("building global ComputeForwardingRule client: %w", err) + } + return client, err +} + +func (m *gcpClient) forwardingRuleClient(ctx context.Context) (*api.ForwardingRulesClient, error) { + opts, err := m.options() + if err != nil { + return nil, err + } + client, err := api.NewForwardingRulesRESTClient(ctx, opts...) + if err != nil { + return nil, fmt.Errorf("building ComputeForwardingRule client: %w", err) + } + return client, err +} diff --git a/pkg/controller/direct/compute/forwardingrule_controller.go b/pkg/controller/direct/compute/forwardingrule_controller.go new file mode 100644 index 00000000000..6e3215b5018 --- /dev/null +++ b/pkg/controller/direct/compute/forwardingrule_controller.go @@ -0,0 +1,471 @@ +// 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. + +package compute + +import ( + "context" + "fmt" + "k8s.io/klog/v2" + "reflect" + + refs "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1" + + gcp "cloud.google.com/go/compute/apiv1" + computepb "cloud.google.com/go/compute/apiv1/computepb" + krm "github.com/GoogleCloudPlatform/k8s-config-connector/apis/compute/v1beta1" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/config" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/directbase" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/registry" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ctrlName = "forwardingrule-controller" + +func init() { + registry.RegisterModel(krm.ComputeForwardingRuleGVK, NewForwardingRuleModel) +} + +func NewForwardingRuleModel(ctx context.Context, config *config.ControllerConfig) (directbase.Model, error) { + return &forwardingRuleModel{config: config}, nil +} + +type forwardingRuleModel struct { + config *config.ControllerConfig +} + +// model implements the Model interface. +var _ directbase.Model = &forwardingRuleModel{} + +type forwardingRuleAdapter struct { + resourceID string + projectID string + Location string + forwardingRulesClient *gcp.ForwardingRulesClient + globalForwardingRulesClient *gcp.GlobalForwardingRulesClient + desired *krm.ComputeForwardingRule + actual *computepb.ForwardingRule +} + +var _ directbase.Adapter = &forwardingRuleAdapter{} + +func (m *forwardingRuleModel) AdapterForObject(ctx context.Context, reader client.Reader, u *unstructured.Unstructured) (directbase.Adapter, error) { + obj := &krm.ComputeForwardingRule{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, &obj); err != nil { + return nil, fmt.Errorf("error converting to %T: %w", obj, err) + } + + // Get ResourceID + resourceID, err := refs.GetResourceID(u) + if err != nil { + return nil, err + } + + // Get projectID + projectID, err := refs.ResolveProjectID(ctx, reader, u) + if err != nil { + return nil, err + } + + // Get network + if obj.Spec.NetworkRef != nil { + networkRef, err := ResolveComputeNetwork(ctx, reader, obj, obj.Spec.NetworkRef) + if err != nil { + return nil, err + + } + obj.Spec.NetworkRef.External = networkRef.External + } + + // Get compute address + if obj.Spec.IpAddress.AddressRef != nil { + computeAddressRef, err := ResolveComputeAddress(ctx, reader, obj, obj.Spec.IpAddress.AddressRef) + if err != nil { + return nil, err + + } + obj.Spec.IpAddress.AddressRef.External = computeAddressRef.External + } + + // Get target ComputeTargetHTTPProxy + if obj.Spec.Target.TargetHTTPProxyRef != nil { + targetHTTPProxyRef, err := ResolveComputeTargetHTTPProxy(ctx, reader, obj, obj.Spec.Target.TargetHTTPProxyRef) + if err != nil { + return nil, err + + } + obj.Spec.Target.TargetHTTPProxyRef.External = targetHTTPProxyRef.External + } + + // Get target TargetVPNGateway + if obj.Spec.Target.TargetVPNGatewayRef != nil { + targetVPNGatewayRef, err := ResolveComputeTargetVPNGateway(ctx, reader, obj, obj.Spec.Target.TargetVPNGatewayRef) + if err != nil { + return nil, err + + } + obj.Spec.Target.TargetVPNGatewayRef.External = targetVPNGatewayRef.External + } + + // Get location + location := obj.Spec.Location + + // Set label managed-by-cnrm: true + obj.ObjectMeta.Labels["managed-by-cnrm"] = "true" + + // Handle TF default values + if obj.Spec.LoadBalancingScheme == nil { + obj.Spec.LoadBalancingScheme = direct.LazyPtr("EXTERNAL") + } + + forwardingRuleAdapter := &forwardingRuleAdapter{ + resourceID: resourceID, + projectID: projectID, + Location: location, + desired: obj, + } + + // Get GCP client + gcpClient, err := newGCPClient(ctx, m.config) + if err != nil { + return nil, fmt.Errorf("building gcp client: %w", err) + } + if location == "global" { + globalForwardingRulesClient, err := gcpClient.globalForwardingRuleClient(ctx) + if err != nil { + return nil, err + } + forwardingRuleAdapter.globalForwardingRulesClient = globalForwardingRulesClient + } else { + forwardingRulesClient, err := gcpClient.forwardingRuleClient(ctx) + if err != nil { + return nil, err + } + forwardingRuleAdapter.forwardingRulesClient = forwardingRulesClient + } + return forwardingRuleAdapter, nil +} + +func (m *forwardingRuleModel) AdapterForURL(ctx context.Context, url string) (directbase.Adapter, error) { + // TODO: Support URLs + return nil, nil +} + +func (a *forwardingRuleAdapter) Find(ctx context.Context) (bool, error) { + if a.resourceID == "" { + return false, nil + } + + log := klog.FromContext(ctx).WithName(ctrlName) + log.V(2).Info("getting ComputeForwardingRule", "name", a.resourceID) + + var err error + forwardingRule := &computepb.ForwardingRule{} + if a.Location == "global" { + req := &computepb.GetGlobalForwardingRuleRequest{ + ForwardingRule: a.resourceID, + Project: a.projectID, + } + forwardingRule, err = a.globalForwardingRulesClient.Get(ctx, req) + if err != nil { + if direct.IsNotFound(err) { + return false, nil + } + return false, fmt.Errorf("getting ComputeForwardingRule %q failed: %w", a.fullyQualifiedName(), err) + } + } else { + req := &computepb.GetForwardingRuleRequest{ + ForwardingRule: a.resourceID, + Region: a.Location, + Project: a.projectID, + } + forwardingRule, err = a.forwardingRulesClient.Get(ctx, req) + if err != nil { + if direct.IsNotFound(err) { + return false, nil + } + return false, fmt.Errorf("getting ComputeForwardingRule %q failed: %w", a.fullyQualifiedName(), err) + } + } + a.actual = forwardingRule + return true, nil +} + +func (a *forwardingRuleAdapter) Create(ctx context.Context, u *unstructured.Unstructured) error { + if a.projectID == "" { + return fmt.Errorf("project is empty") + } + if a.resourceID == "" { + return fmt.Errorf("resourceID is empty") + } + + log := klog.FromContext(ctx).WithName(ctrlName) + log.V(2).Info("creating ComputeForwardingRule", "name", a.resourceID) + mapCtx := &direct.MapContext{} + + a.desired.Labels["managed-by-cnrm"] = "true" + desired := a.desired.DeepCopy() + + forwardingRule := ComputeForwardingRuleSpec_ToProto(mapCtx, &desired.Spec) + if mapCtx.Err() != nil { + return mapCtx.Err() + } + forwardingRule.Name = direct.LazyPtr(a.resourceID) + forwardingRule.Labels = desired.Labels + + var err error + op := &gcp.Operation{} + if a.Location == "global" { + req := &computepb.InsertGlobalForwardingRuleRequest{ + ForwardingRuleResource: forwardingRule, + Project: a.projectID, + } + op, err = a.globalForwardingRulesClient.Insert(ctx, req) + } else { + req := &computepb.InsertForwardingRuleRequest{ + ForwardingRuleResource: forwardingRule, + Region: a.Location, + Project: a.projectID, + } + op, err = a.forwardingRulesClient.Insert(ctx, req) + } + if err != nil { + return fmt.Errorf("creating ComputeForwardingRule %s failed: %w", a.fullyQualifiedName(), err) + } + log.V(2).Info("successfully created ComputeForwardingRule", "name", a.fullyQualifiedName()) + // Get the created resource + created := &computepb.ForwardingRule{} + if a.Location == "global" { + getReq := &computepb.GetGlobalForwardingRuleRequest{ + ForwardingRule: a.resourceID, + Project: a.projectID, + } + created, err = a.globalForwardingRulesClient.Get(ctx, getReq) + } else { + getReq := &computepb.GetForwardingRuleRequest{ + ForwardingRule: a.resourceID, + Region: a.Location, + Project: a.projectID, + } + created, err = a.forwardingRulesClient.Get(ctx, getReq) + } + if err != nil { + return fmt.Errorf("getting ComputeForwardingRule %q failed: %w", a.fullyQualifiedName(), err) + } + + status := &krm.ComputeForwardingRuleStatus{ + LabelFingerprint: created.LabelFingerprint, + CreationTimestamp: op.Proto().InsertTime, + SelfLink: created.SelfLink, + } + return setStatus(u, status) +} + +func (a *forwardingRuleAdapter) Update(ctx context.Context, u *unstructured.Unstructured) error { + if a.resourceID == "" { + return fmt.Errorf("resourceID is empty") + } + + log := klog.FromContext(ctx).WithName(ctrlName) + log.V(2).Info("updating ComputeForwardingRule", "name", a.resourceID) + mapCtx := &direct.MapContext{} + + desired := a.desired.DeepCopy() + forwardingRule := ComputeForwardingRuleSpec_ToProto(mapCtx, &desired.Spec) + if mapCtx.Err() != nil { + return mapCtx.Err() + } + forwardingRule.Name = direct.LazyPtr(a.resourceID) + forwardingRule.Labels = desired.Labels + + // Patch only support update on networkTier field, which KCC does not support yet. + // Use setTarget and setLabels to update target and labels fields. + var err error + op := &gcp.Operation{} + updated := &computepb.ForwardingRule{} + // TODO(yuhou): Checked the realGCP logs, setLabels request is being sent even when there are no updates to labels. + // That might because of the generated labelsFingerPrint? + if a.Location == "global" { + setLabelsReq := &computepb.SetLabelsGlobalForwardingRuleRequest{ + Resource: a.resourceID, + GlobalSetLabelsRequestResource: &computepb.GlobalSetLabelsRequest{LabelFingerprint: a.actual.LabelFingerprint, Labels: forwardingRule.Labels}, + Project: a.projectID, + } + op, err = a.globalForwardingRulesClient.SetLabels(ctx, setLabelsReq) + } else { + setLabelsReq := &computepb.SetLabelsForwardingRuleRequest{ + Resource: a.resourceID, + RegionSetLabelsRequestResource: &computepb.RegionSetLabelsRequest{LabelFingerprint: a.actual.LabelFingerprint, Labels: forwardingRule.Labels}, + Project: a.projectID, + Region: a.Location, + } + op, err = a.forwardingRulesClient.SetLabels(ctx, setLabelsReq) + } + if err != nil { + return fmt.Errorf("updating ComputeForwardingRule labels %s failed: %w", a.fullyQualifiedName(), err) + } + err = op.Wait(ctx) + if err != nil { + return fmt.Errorf("waiting ComputeForwardingRule %s update labels failed: %w", a.fullyQualifiedName(), err) + } + log.V(2).Info("successfully updated ComputeForwardingRule labels", "name", a.fullyQualifiedName()) + // Get the updated resource + if a.Location == "global" { + getReq := &computepb.GetGlobalForwardingRuleRequest{ + ForwardingRule: a.resourceID, + Project: a.projectID, + } + updated, err = a.globalForwardingRulesClient.Get(ctx, getReq) + } else { + getReq := &computepb.GetForwardingRuleRequest{ + ForwardingRule: a.resourceID, + Region: a.Location, + Project: a.projectID, + } + updated, err = a.forwardingRulesClient.Get(ctx, getReq) + } + if err != nil { + return fmt.Errorf("getting ComputeForwardingRule %q failed: %w", a.resourceID, err) + } + + // setTarget request is sent when there are updates to target. + if !reflect.DeepEqual(forwardingRule.Target, a.actual.Target) { + if a.Location == "global" { + setTargetReq := &computepb.SetTargetGlobalForwardingRuleRequest{ + ForwardingRule: a.resourceID, + TargetReferenceResource: &computepb.TargetReference{Target: forwardingRule.Target}, + Project: a.projectID, + } + op, err = a.globalForwardingRulesClient.SetTarget(ctx, setTargetReq) + } else { + setTargetReq := &computepb.SetTargetForwardingRuleRequest{ + ForwardingRule: a.resourceID, + TargetReferenceResource: &computepb.TargetReference{Target: forwardingRule.Target}, + Project: a.projectID, + Region: a.Location, + } + op, err = a.forwardingRulesClient.SetTarget(ctx, setTargetReq) + } + if err != nil { + return fmt.Errorf("updating ComputeForwardingRule target %s failed: %w", a.fullyQualifiedName(), err) + } + err = op.Wait(ctx) + if err != nil { + return fmt.Errorf("waiting ComputeForwardingRule %s update target failed: %w", a.fullyQualifiedName(), err) + } + log.V(2).Info("successfully updated ComputeForwardingRule target", "name", a.fullyQualifiedName()) + } + + // Get the updated resource + if a.Location == "global" { + getReq := &computepb.GetGlobalForwardingRuleRequest{ + ForwardingRule: a.resourceID, + Project: a.projectID, + } + updated, err = a.globalForwardingRulesClient.Get(ctx, getReq) + } else { + getReq := &computepb.GetForwardingRuleRequest{ + ForwardingRule: a.resourceID, + Region: a.Location, + Project: a.projectID, + } + updated, err = a.forwardingRulesClient.Get(ctx, getReq) + } + if err != nil { + return fmt.Errorf("getting ComputeForwardingRule %q failed: %w", a.resourceID, err) + } + + status := &krm.ComputeForwardingRuleStatus{ + LabelFingerprint: updated.LabelFingerprint, + CreationTimestamp: op.Proto().InsertTime, + SelfLink: updated.SelfLink, + } + return setStatus(u, status) +} + +func (a *forwardingRuleAdapter) Export(ctx context.Context) (*unstructured.Unstructured, error) { + // TODO(kcc) + return nil, nil +} + +// Delete implements the Adapter interface. +func (a *forwardingRuleAdapter) Delete(ctx context.Context) (bool, error) { + if a.resourceID == "" { + return false, fmt.Errorf("resourceID is empty") + } + + log := klog.FromContext(ctx).WithName(ctrlName) + log.V(2).Info("deleting ComputeForwardingRule", "name", a.resourceID) + + exist, err := a.Find(ctx) + if err != nil { + return false, err + } + if !exist { + // return (false, nil) if the object was not found but should be presumed deleted. + return false, nil + } + + op := &gcp.Operation{} + if a.Location == "global" { + req := &computepb.DeleteGlobalForwardingRuleRequest{ + ForwardingRule: a.resourceID, + Project: a.projectID, + } + op, err = a.globalForwardingRulesClient.Delete(ctx, req) + } else { + req := &computepb.DeleteForwardingRuleRequest{ + ForwardingRule: a.resourceID, + Region: a.Location, + Project: a.projectID, + } + op, err = a.forwardingRulesClient.Delete(ctx, req) + } + if err != nil { + return false, fmt.Errorf("deleting ComputeForwardingRule %s failed: %w", a.resourceID, err) + } + err = op.Wait(ctx) + if err != nil { + return false, fmt.Errorf("waiting ComputeForwardingRule %s delete failed: %w", a.resourceID, err) + } + log.V(2).Info("successfully deleted ComputeForwardingRule", "name", a.resourceID) + return true, nil +} + +func (a *forwardingRuleAdapter) fullyQualifiedName() string { + if a.Location == "global" { + return fmt.Sprintf("projects/%s/global/forwardingRules/%s", a.projectID, a.resourceID) + } + return fmt.Sprintf("projects/%s/regions/%s/forwardingRules/%s", a.projectID, a.Location, a.resourceID) +} + +func setStatus(u *unstructured.Unstructured, typedStatus any) error { + status, err := runtime.DefaultUnstructuredConverter.ToUnstructured(typedStatus) + if err != nil { + return fmt.Errorf("error converting status to unstructured: %w", err) + } + + old, _, _ := unstructured.NestedMap(u.Object, "status") + if old != nil { + status["conditions"] = old["conditions"] + status["observedGeneration"] = old["observedGeneration"] + } + + u.Object["status"] = status + + return nil +} diff --git a/pkg/controller/direct/compute/refs.go b/pkg/controller/direct/compute/refs.go index 62e9faf8b94..6022875ae63 100644 --- a/pkg/controller/direct/compute/refs.go +++ b/pkg/controller/direct/compute/refs.go @@ -61,10 +61,20 @@ func ResolveComputeNetwork(ctx context.Context, reader client.Reader, src client return nil, err } + resourceID, err := refs.GetResourceID(computeNetwork) + if err != nil { + return nil, err + } + + projectID, err := refs.ResolveProjectID(ctx, reader, computeNetwork) + if err != nil { + return nil, err + } + // targetField: self_link // See compute servicemappings for details return &refs.ComputeNetworkRef{ - External: computeNetwork.GetSelfLink()}, nil + External: fmt.Sprintf("projects/%s/global/networks/%s", projectID, resourceID)}, nil } func ResolveComputeSubnetwork(ctx context.Context, reader client.Reader, src client.Object, ref *refs.ComputeSubnetworkRef) (*refs.ComputeSubnetworkRef, error) { @@ -101,9 +111,12 @@ func ResolveComputeSubnetwork(ctx context.Context, reader client.Reader, src cli } // targetField: self_link // See compute servicemappings for details + selfLink, _, err := unstructured.NestedString(computeSubnetwork.Object, "status", "selfLink") + if err != nil || selfLink == "" { + return nil, fmt.Errorf("cannot get selfLink for referenced %s %v (status.selfLink is empty)", computeSubnetwork.GetKind(), computeSubnetwork.GetNamespace()) + } return &refs.ComputeSubnetworkRef{ - External: computeSubnetwork.GetSelfLink(), - }, nil + External: selfLink}, nil } func ResolveComputeAddress(ctx context.Context, reader client.Reader, src client.Object, ref *refs.ComputeAddressRef) (*refs.ComputeAddressRef, error) { @@ -141,8 +154,8 @@ func ResolveComputeAddress(ctx context.Context, reader client.Reader, src client // targetField: address // See compute servicemappings for details - address, _, _ := unstructured.NestedString(computeAddress.Object, "spec", "address") - if address == "" { + address, _, err := unstructured.NestedString(computeAddress.Object, "spec", "address") + if err != nil || address == "" { return nil, fmt.Errorf("cannot get address for referenced %s %v (spec.address is empty)", computeAddress.GetKind(), computeAddress.GetNamespace()) } return &refs.ComputeAddressRef{ @@ -184,8 +197,12 @@ func ResolveComputeBackendService(ctx context.Context, reader client.Reader, src // targetField: self_link // See compute servicemappings for details + selfLink, _, err := unstructured.NestedString(computeBackendService.Object, "status", "selfLink") + if err != nil || selfLink == "" { + return nil, fmt.Errorf("cannot get selfLink for referenced %s %v (status.selfLink is empty)", computeBackendService.GetKind(), computeBackendService.GetNamespace()) + } return &refs.ComputeBackendServiceRef{ - External: computeBackendService.GetSelfLink()}, nil + External: selfLink}, nil } func ResolveComputeServiceAttachment(ctx context.Context, reader client.Reader, src client.Object, ref *refs.ComputeServiceAttachmentRef) (*refs.ComputeServiceAttachmentRef, error) { @@ -223,8 +240,12 @@ func ResolveComputeServiceAttachment(ctx context.Context, reader client.Reader, // targetField: self_link // See compute servicemappings for details + selfLink, _, err := unstructured.NestedString(computeServiceAttachment.Object, "status", "selfLink") + if err != nil || selfLink == "" { + return nil, fmt.Errorf("cannot get selfLink for referenced %s %v (status.selfLink is empty)", computeServiceAttachment.GetKind(), computeServiceAttachment.GetNamespace()) + } return &refs.ComputeServiceAttachmentRef{ - External: computeServiceAttachment.GetSelfLink()}, nil + External: selfLink}, nil } func ResolveComputeTargetGrpcProxy(ctx context.Context, reader client.Reader, src client.Object, ref *refs.ComputeTargetGrpcProxyRef) (*refs.ComputeTargetGrpcProxyRef, error) { @@ -262,8 +283,12 @@ func ResolveComputeTargetGrpcProxy(ctx context.Context, reader client.Reader, sr // targetField: self_link // See compute servicemappings for details + selfLink, _, err := unstructured.NestedString(computeTargetGrpcProxy.Object, "status", "selfLink") + if err != nil || selfLink == "" { + return nil, fmt.Errorf("cannot get selfLink for referenced %s %v (status.selfLink is empty)", computeTargetGrpcProxy.GetKind(), computeTargetGrpcProxy.GetNamespace()) + } return &refs.ComputeTargetGrpcProxyRef{ - External: computeTargetGrpcProxy.GetSelfLink()}, nil + External: selfLink}, nil } func ResolveComputeTargetHTTPProxy(ctx context.Context, reader client.Reader, src client.Object, ref *refs.ComputeTargetHTTPProxyRef) (*refs.ComputeTargetHTTPProxyRef, error) { @@ -301,8 +326,12 @@ func ResolveComputeTargetHTTPProxy(ctx context.Context, reader client.Reader, sr // targetField: self_link // See compute servicemappings for details + selfLink, _, err := unstructured.NestedString(computeTargetHTTPProxy.Object, "status", "selfLink") + if err != nil || selfLink == "" { + return nil, fmt.Errorf("cannot get selfLink for referenced %s %v (status.selfLink is empty)", computeTargetHTTPProxy.GetKind(), computeTargetHTTPProxy.GetNamespace()) + } return &refs.ComputeTargetHTTPProxyRef{ - External: computeTargetHTTPProxy.GetSelfLink()}, nil + External: selfLink}, nil } func ResolveComputeTargetHTTPSProxy(ctx context.Context, reader client.Reader, src client.Object, ref *refs.ComputeTargetHTTPSProxyRef) (*refs.ComputeTargetHTTPSProxyRef, error) { @@ -340,8 +369,12 @@ func ResolveComputeTargetHTTPSProxy(ctx context.Context, reader client.Reader, s // targetField: self_link // See compute servicemappings for details + selfLink, _, err := unstructured.NestedString(computeTargetHTTPSProxy.Object, "status", "selfLink") + if err != nil || selfLink == "" { + return nil, fmt.Errorf("cannot get selfLink for referenced %s %v (status.selfLink is empty)", computeTargetHTTPSProxy.GetKind(), computeTargetHTTPSProxy.GetNamespace()) + } return &refs.ComputeTargetHTTPSProxyRef{ - External: computeTargetHTTPSProxy.GetSelfLink()}, nil + External: selfLink}, nil } func ResolveComputeTargetSSLProxy(ctx context.Context, reader client.Reader, src client.Object, ref *refs.ComputeTargetSSLProxyRef) (*refs.ComputeTargetSSLProxyRef, error) { @@ -379,8 +412,12 @@ func ResolveComputeTargetSSLProxy(ctx context.Context, reader client.Reader, src // targetField: self_link // See compute servicemappings for details + selfLink, _, err := unstructured.NestedString(computeTargetSSLProxy.Object, "status", "selfLink") + if err != nil || selfLink == "" { + return nil, fmt.Errorf("cannot get selfLink for referenced %s %v (status.selfLink is empty)", computeTargetSSLProxy.GetKind(), computeTargetSSLProxy.GetNamespace()) + } return &refs.ComputeTargetSSLProxyRef{ - External: computeTargetSSLProxy.GetSelfLink()}, nil + External: selfLink}, nil } func ResolveComputeTargetTCPProxy(ctx context.Context, reader client.Reader, src client.Object, ref *refs.ComputeTargetTCPProxyRef) (*refs.ComputeTargetTCPProxyRef, error) { @@ -418,8 +455,12 @@ func ResolveComputeTargetTCPProxy(ctx context.Context, reader client.Reader, src // targetField: self_link // See compute servicemappings for details + selfLink, _, err := unstructured.NestedString(computeTargetTCPProxy.Object, "status", "selfLink") + if err != nil || selfLink == "" { + return nil, fmt.Errorf("cannot get selfLink for referenced %s %v (status.selfLink is empty)", computeTargetTCPProxy.GetKind(), computeTargetTCPProxy.GetNamespace()) + } return &refs.ComputeTargetTCPProxyRef{ - External: computeTargetTCPProxy.GetSelfLink()}, nil + External: selfLink}, nil } func ResolveComputeTargetVPNGateway(ctx context.Context, reader client.Reader, src client.Object, ref *refs.ComputeTargetVPNGatewayRef) (*refs.ComputeTargetVPNGatewayRef, error) { @@ -457,8 +498,12 @@ func ResolveComputeTargetVPNGateway(ctx context.Context, reader client.Reader, s // targetField: self_link // See compute servicemappings for details + selfLink, _, err := unstructured.NestedString(computeTargetVPNGateway.Object, "status", "selfLink") + if err != nil || selfLink == "" { + return nil, fmt.Errorf("cannot get selfLink for referenced %s %v (status.selfLink is empty)", computeTargetVPNGateway.GetKind(), computeTargetVPNGateway.GetNamespace()) + } return &refs.ComputeTargetVPNGatewayRef{ - External: computeTargetVPNGateway.GetSelfLink()}, nil + External: selfLink}, nil } func resolveResourceName(ctx context.Context, reader client.Reader, key client.ObjectKey, gvk schema.GroupVersionKind) (*unstructured.Unstructured, error) { diff --git a/pkg/controller/direct/register/register.go b/pkg/controller/direct/register/register.go index 7da93089268..b1296ed8ba3 100644 --- a/pkg/controller/direct/register/register.go +++ b/pkg/controller/direct/register/register.go @@ -18,6 +18,7 @@ import ( _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/alloydb" _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/apikeys" _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/cloudbuild" + _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/compute" _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/dataform" _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/gkehub" _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/logging" diff --git a/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/globalcomputeforwardingrule/_generated_object_globalcomputeforwardingrule.golden.yaml b/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/globalcomputeforwardingrule/_generated_object_globalcomputeforwardingrule.golden.yaml index ef5044232e2..3595b207f5e 100644 --- a/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/globalcomputeforwardingrule/_generated_object_globalcomputeforwardingrule.golden.yaml +++ b/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/globalcomputeforwardingrule/_generated_object_globalcomputeforwardingrule.golden.yaml @@ -18,11 +18,10 @@ metadata: annotations: cnrm.cloud.google.com/management-conflict-prevention-policy: none cnrm.cloud.google.com/project-id: ${projectId} - cnrm.cloud.google.com/state-into-spec: merge finalizers: - cnrm.cloud.google.com/finalizer - cnrm.cloud.google.com/deletion-defender - generation: 3 + generation: 2 labels: cnrm-test: "true" label-one: value-one @@ -32,13 +31,11 @@ spec: description: A global forwarding rule ipAddress: ip: 0.0.0.0 - ipProtocol: TCP loadBalancingScheme: INTERNAL_SELF_MANAGED location: global networkRef: name: default portRange: "80" - resourceID: computeglobalforwardingrule-${uniqueId} target: targetHTTPProxyRef: name: computetargethttpproxy-2-${uniqueId} @@ -49,6 +46,7 @@ status: reason: UpToDate status: "True" type: Ready + creationTimestamp: "1970-01-01T00:00:00Z" labelFingerprint: abcdef0123A= - observedGeneration: 3 + observedGeneration: 2 selfLink: https://www.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/computeglobalforwardingrule-${uniqueId} diff --git a/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/globalcomputeforwardingrule/_http.log b/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/globalcomputeforwardingrule/_http.log index 58c62ac0c8d..cc47a8cf096 100644 --- a/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/globalcomputeforwardingrule/_http.log +++ b/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/globalcomputeforwardingrule/_http.log @@ -709,9 +709,10 @@ X-Xss-Protection: 0 --- -GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/${forwardingRuleID}?alt=json +GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/${forwardingRuleID} Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}&forwarding_rule=computeglobalforwardingrule-${uniqueId} 404 Not Found Cache-Control: private @@ -740,9 +741,10 @@ X-Xss-Protection: 0 --- -POST https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules?alt=json +POST https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId} { "IPAddress": "0.0.0.0", @@ -787,41 +789,10 @@ X-Xss-Protection: 0 --- -GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -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 - -{ - "endTime": "2024-04-01T12:34:56.123456Z", - "id": "000000000000000000000", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "compute#operation", - "name": "${operationID}", - "operationType": "insert", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID}", - "startTime": "2024-04-01T12:34:56.123456Z", - "status": "DONE", - "targetId": "${forwardingRulesId}", - "targetLink": "https://www.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/computeglobalforwardingrule-${uniqueId}", - "user": "user@example.com" -} - ---- - -GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/${forwardingRuleID}?alt=json +GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/${forwardingRuleID} Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}&forwarding_rule=computeglobalforwardingrule-${uniqueId} 200 OK Cache-Control: private @@ -859,9 +830,10 @@ X-Xss-Protection: 0 --- -POST https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/${forwardingRuleID}/setLabels?alt=json +POST https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/${forwardingRuleID}/setLabels Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}&resource=computeglobalforwardingrule-${uniqueId} { "labelFingerprint": "abcdef0123A=", @@ -901,8 +873,10 @@ X-Xss-Protection: 0 --- -GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID} +Content-Type: application/json +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}&operation=${operationID} 200 OK Cache-Control: private @@ -933,9 +907,10 @@ X-Xss-Protection: 0 --- -GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/${forwardingRuleID}?alt=json +GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/${forwardingRuleID} Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}&forwarding_rule=computeglobalforwardingrule-${uniqueId} 200 OK Cache-Control: private @@ -973,9 +948,10 @@ X-Xss-Protection: 0 --- -POST https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/${forwardingRuleID}/setTarget?alt=json +POST https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/${forwardingRuleID}/setTarget Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}&forwarding_rule=computeglobalforwardingrule-${uniqueId} { "target": "https://www.googleapis.com/compute/v1/projects/${projectId}/global/targetHttpProxies/computetargethttpproxy-2-${uniqueId}" @@ -1009,8 +985,10 @@ X-Xss-Protection: 0 --- -GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID} +Content-Type: application/json +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}&operation=${operationID} 200 OK Cache-Control: private @@ -1041,9 +1019,10 @@ X-Xss-Protection: 0 --- -GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/${forwardingRuleID}?alt=json +GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/${forwardingRuleID} Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}&forwarding_rule=computeglobalforwardingrule-${uniqueId} 200 OK Cache-Control: private @@ -1081,9 +1060,10 @@ X-Xss-Protection: 0 --- -DELETE https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/${forwardingRuleID}?alt=json +DELETE https://compute.googleapis.com/compute/v1/projects/${projectId}/global/forwardingRules/${forwardingRuleID} Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}&forwarding_rule=computeglobalforwardingrule-${uniqueId} 200 OK Cache-Control: private @@ -1113,8 +1093,10 @@ X-Xss-Protection: 0 --- -GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID} +Content-Type: application/json +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}&operation=${operationID} 200 OK Cache-Control: private diff --git a/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/regionalcomputeforwardingrule/_generated_object_regionalcomputeforwardingrule.golden.yaml b/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/regionalcomputeforwardingrule/_generated_object_regionalcomputeforwardingrule.golden.yaml index 496880bf440..b5c35225ee1 100644 --- a/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/regionalcomputeforwardingrule/_generated_object_regionalcomputeforwardingrule.golden.yaml +++ b/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/regionalcomputeforwardingrule/_generated_object_regionalcomputeforwardingrule.golden.yaml @@ -1,28 +1,13 @@ -# 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: ComputeForwardingRule metadata: annotations: cnrm.cloud.google.com/management-conflict-prevention-policy: none cnrm.cloud.google.com/project-id: ${projectId} - cnrm.cloud.google.com/state-into-spec: merge finalizers: - cnrm.cloud.google.com/finalizer - cnrm.cloud.google.com/deletion-defender - generation: 2 + generation: 1 labels: cnrm-test: "true" label-one: value-two @@ -34,10 +19,7 @@ spec: addressRef: name: computeraddress-${uniqueId} ipProtocol: ESP - loadBalancingScheme: EXTERNAL location: us-central1 - networkTier: PREMIUM - resourceID: computeregionalforwardingrule-${uniqueId} target: targetVPNGatewayRef: name: computetargetvpngateway-${uniqueId} @@ -50,5 +32,5 @@ status: type: Ready creationTimestamp: "1970-01-01T00:00:00Z" labelFingerprint: abcdef0123A= - observedGeneration: 2 + observedGeneration: 1 selfLink: https://www.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/computeregionalforwardingrule-${uniqueId} diff --git a/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/regionalcomputeforwardingrule/_http.log b/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/regionalcomputeforwardingrule/_http.log index e5ab8b9dc27..0ba822593e9 100644 --- a/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/regionalcomputeforwardingrule/_http.log +++ b/pkg/test/resourcefixture/testdata/basic/compute/v1beta1/computeforwardingrule/regionalcomputeforwardingrule/_http.log @@ -482,9 +482,10 @@ X-Xss-Protection: 0 --- -GET https://compute.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/${forwardingRuleID}?alt=json +GET https://compute.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/${forwardingRuleID} Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}®ion=us-central1&forwarding_rule=computeregionalforwardingrule-${uniqueId} 404 Not Found Cache-Control: private @@ -513,9 +514,10 @@ X-Xss-Protection: 0 --- -POST https://compute.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules?alt=json +POST https://compute.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}®ion=us-central1 { "IPAddress": "8.8.8.8", @@ -528,7 +530,6 @@ User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 t }, "loadBalancingScheme": "EXTERNAL", "name": "computeregionalforwardingrule-${uniqueId}", - "region": "projects/${projectId}/global/regions/us-central1", "target": "https://www.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/targetVpnGateways/computetargetvpngateway-${uniqueId}" } @@ -560,41 +561,10 @@ X-Xss-Protection: 0 --- -GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -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 - -{ - "endTime": "2024-04-01T12:34:56.123456Z", - "id": "000000000000000000000", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "compute#operation", - "name": "${operationID}", - "operationType": "insert", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID}", - "startTime": "2024-04-01T12:34:56.123456Z", - "status": "DONE", - "targetId": "${forwardingRulesId}", - "targetLink": "https://www.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/computeregionalforwardingrule-${uniqueId}", - "user": "user@example.com" -} - ---- - -GET https://compute.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/${forwardingRuleID}?alt=json +GET https://compute.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/${forwardingRuleID} Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}®ion=us-central1&forwarding_rule=computeregionalforwardingrule-${uniqueId} 200 OK Cache-Control: private @@ -624,22 +594,22 @@ X-Xss-Protection: 0 "loadBalancingScheme": "EXTERNAL", "name": "computeregionalforwardingrule-${uniqueId}", "networkTier": "PREMIUM", - "region": "projects/${projectId}/global/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/computeregionalforwardingrule-${uniqueId}", "target": "https://www.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/targetVpnGateways/computetargetvpngateway-${uniqueId}" } --- -POST https://compute.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/${forwardingRuleID}/setLabels?alt=json +POST https://compute.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/${forwardingRuleID}/setLabels Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}®ion=us-central1&resource=computeregionalforwardingrule-${uniqueId} { "labelFingerprint": "abcdef0123A=", "labels": { "cnrm-test": "true", - "label-one": "value-one", + "label-one": "value-two", "managed-by-cnrm": "true" } } @@ -673,41 +643,10 @@ X-Xss-Protection: 0 --- -GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -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 - -{ - "endTime": "2024-04-01T12:34:56.123456Z", - "id": "000000000000000000000", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "compute#operation", - "name": "${operationID}", - "operationType": "SetLabels", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID}", - "startTime": "2024-04-01T12:34:56.123456Z", - "status": "DONE", - "targetId": "${forwardingRulesId}", - "targetLink": "https://www.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/computeregionalforwardingrule-${uniqueId}", - "user": "user@example.com" -} - ---- - -GET https://compute.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/${forwardingRuleID}?alt=json +GET https://compute.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/${forwardingRuleID} Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}®ion=us-central1&forwarding_rule=computeregionalforwardingrule-${uniqueId} 200 OK Cache-Control: private @@ -731,22 +670,22 @@ X-Xss-Protection: 0 "labelFingerprint": "abcdef0123A=", "labels": { "cnrm-test": "true", - "label-one": "value-one", + "label-one": "value-two", "managed-by-cnrm": "true" }, "loadBalancingScheme": "EXTERNAL", "name": "computeregionalforwardingrule-${uniqueId}", "networkTier": "PREMIUM", - "region": "projects/${projectId}/global/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/computeregionalforwardingrule-${uniqueId}", "target": "https://www.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/targetVpnGateways/computetargetvpngateway-${uniqueId}" } --- -DELETE https://compute.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/${forwardingRuleID}?alt=json +DELETE https://compute.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/${forwardingRuleID} Content-Type: application/json -User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}®ion=us-central1&forwarding_rule=computeregionalforwardingrule-${uniqueId} 200 OK Cache-Control: private @@ -776,10 +715,12 @@ X-Xss-Protection: 0 --- -GET https://compute.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +GET https://compute.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/${forwardingRuleID} +Content-Type: application/json +User-Agent: kcc/controller-manager +x-goog-request-params: project=${projectId}®ion=us-central1&forwarding_rule=computeregionalforwardingrule-${uniqueId} -200 OK +404 Not Found Cache-Control: private Content-Type: application/json; charset=UTF-8 Server: ESF @@ -791,19 +732,17 @@ X-Frame-Options: SAMEORIGIN X-Xss-Protection: 0 { - "endTime": "2024-04-01T12:34:56.123456Z", - "id": "000000000000000000000", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "compute#operation", - "name": "${operationID}", - "operationType": "delete", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/${projectId}/global/operations/${operationID}", - "startTime": "2024-04-01T12:34:56.123456Z", - "status": "DONE", - "targetId": "${forwardingRulesId}", - "targetLink": "https://www.googleapis.com/compute/v1/projects/${projectId}/regions/us-central1/forwardingRules/computeregionalforwardingrule-${uniqueId}", - "user": "user@example.com" + "error": { + "code": 404, + "errors": [ + { + "domain": "global", + "message": "forwardingRule \"projects/${projectId}/regions/us-central1/forwardingRules/computeregionalforwardingrule-${uniqueId}\" not found", + "reason": "notFound" + } + ], + "message": "forwardingRule \"projects/${projectId}/regions/us-central1/forwardingRules/computeregionalforwardingrule-${uniqueId}\" not found" + } } --- diff --git a/scripts/github-actions/tests-e2e-fixtures b/scripts/github-actions/tests-e2e-fixtures index 30c33324f35..8704155827d 100755 --- a/scripts/github-actions/tests-e2e-fixtures +++ b/scripts/github-actions/tests-e2e-fixtures @@ -27,6 +27,9 @@ export KUBEBUILDER_ASSETS=$(go run sigs.k8s.io/controller-runtime/tools/setup-en # so as we are moving resources to direct actuation, we add them here. # e.g. export KCC_USE_DIRECT_RECONCILERS=MonitoringDashboard +echo "Using direct controllers: SQLInstance,ComputeForwardingRule" +export KCC_USE_DIRECT_RECONCILERS=SQLInstance,ComputeForwardingRule + echo "Running fixtures in tests/e2e..." RUN_E2E=1 \ @@ -34,5 +37,4 @@ GOLDEN_OBJECT_CHECKS=1 \ GOLDEN_REQUEST_CHECKS=1 \ E2E_KUBE_TARGET=envtest \ E2E_GCP_TARGET=mock \ -KCC_USE_DIRECT_RECONCILERS="SQLInstance" \ go test -test.count=1 -timeout 1h30m -v ./tests/e2e -run TestAllInSeries/fixtures \ No newline at end of file