diff --git a/.github/workflows/build-push.yml b/.github/workflows/build-push.yml index f03e17ab7..8222acc3e 100644 --- a/.github/workflows/build-push.yml +++ b/.github/workflows/build-push.yml @@ -27,6 +27,7 @@ jobs: index.docker.io:443 registry-1.docker.io:443 production.cloudflare.docker.com:443 + production.cloudfront.docker.com:443 gcr.io:443 golang.org:443 go.dev:443 diff --git a/.github/workflows/e2e-test.yaml b/.github/workflows/e2e-test.yaml index 1eacba845..706e8c715 100644 --- a/.github/workflows/e2e-test.yaml +++ b/.github/workflows/e2e-test.yaml @@ -102,6 +102,7 @@ jobs: registry-1.docker.io:443 auth.docker.io:443 production.cloudflare.docker.com:443 + production.cloudfront.docker.com:443 storage.googleapis.com:443 registry.k8s.io:443 *.pkg.dev:443 diff --git a/.github/workflows/e2e-upgrade-test.yaml b/.github/workflows/e2e-upgrade-test.yaml index d5e8c35af..87ed15829 100644 --- a/.github/workflows/e2e-upgrade-test.yaml +++ b/.github/workflows/e2e-upgrade-test.yaml @@ -66,6 +66,7 @@ jobs: registry-1.docker.io:443 auth.docker.io:443 production.cloudflare.docker.com:443 + production.cloudfront.docker.com:443 storage.googleapis.com:443 registry.k8s.io:443 *.pkg.dev:443 diff --git a/.github/workflows/go-analyze.yml b/.github/workflows/go-analyze.yml index e1697a338..2b6db9a3e 100644 --- a/.github/workflows/go-analyze.yml +++ b/.github/workflows/go-analyze.yml @@ -56,6 +56,7 @@ jobs: *.githubusercontent.com:443 auth.docker.io:443 production.cloudflare.docker.com:443 + production.cloudfront.docker.com:443 vuln.go.dev:443 storage.googleapis.com:443 golangci-lint.run:443 diff --git a/.github/workflows/pull_request_ci.yaml b/.github/workflows/pull_request_ci.yaml index a37805b69..30ba69669 100644 --- a/.github/workflows/pull_request_ci.yaml +++ b/.github/workflows/pull_request_ci.yaml @@ -127,6 +127,7 @@ jobs: registry-1.docker.io:443 auth.docker.io:443 production.cloudflare.docker.com:443 + production.cloudfront.docker.com:443 gcr.io:443 storage.googleapis.com:443 diff --git a/Makefile b/Makefile index 1dd454714..aa7601c7a 100644 --- a/Makefile +++ b/Makefile @@ -154,7 +154,7 @@ docs: .PHONY: test test: generate fmt vet envtest ## Run tests. - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use ${ENVTEST_K8S_VERSION#v} --bin-dir $(CACHE_BIN) -p path)" go test -race -timeout 60s `go list ./... | grep -v ./mock$$` -coverprofile cover.out.tmp + KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use ${ENVTEST_K8S_VERSION#v} --bin-dir $(CACHE_BIN) -p path)" go test -timeout 60s `go list ./... | grep -v ./mock$$` -coverpkg=./... -coverprofile cover.out.tmp grep -v "zz_generated.*" cover.out.tmp > cover.out rm cover.out.tmp diff --git a/go.mod b/go.mod index 3702deb34..170ef17f2 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( go.uber.org/automaxprocs v1.6.0 go.uber.org/mock v0.6.0 go4.org/netipx v0.0.0-20231129151722-fdeea329fbba - golang.org/x/mod v0.34.0 + golang.org/x/mod v0.35.0 k8s.io/api v0.35.3 k8s.io/apimachinery v0.35.3 k8s.io/client-go v0.35.3 @@ -137,13 +137,13 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/ratelimit v0.3.1 // indirect go.uber.org/zap v1.27.1 // indirect - golang.org/x/net v0.53.0 // indirect + golang.org/x/net v0.55.0 // indirect golang.org/x/oauth2 v0.35.0 // indirect - golang.org/x/sys v0.43.0 // indirect - golang.org/x/term v0.42.0 // indirect - golang.org/x/text v0.36.0 // indirect + golang.org/x/sys v0.45.0 // indirect + golang.org/x/term v0.43.0 // indirect + golang.org/x/text v0.37.0 // indirect golang.org/x/time v0.12.0 // indirect - golang.org/x/tools v0.43.0 // indirect + golang.org/x/tools v0.44.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260406210006-6f92a3bedf2d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d // indirect diff --git a/go.sum b/go.sum index bea21a143..932ae8e85 100644 --- a/go.sum +++ b/go.sum @@ -321,28 +321,28 @@ go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= -golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= -golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= -golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= -golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= -golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= -golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= +golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= +golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= +golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= +golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= -golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= -golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= -golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= +golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= -golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s= -golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= +golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= +golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0= gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= diff --git a/internal/controller/linodecluster_controller.go b/internal/controller/linodecluster_controller.go index c40c8a292..729e77f01 100644 --- a/internal/controller/linodecluster_controller.go +++ b/internal/controller/linodecluster_controller.go @@ -73,17 +73,11 @@ type LinodeClusterReconciler struct { // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. -func (r *LinodeClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *LinodeClusterReconciler) Reconcile(ctx context.Context, linodeCluster *infrav1alpha2.LinodeCluster) (ctrl.Result, error) { ctx, cancel := context.WithTimeout(ctx, reconciler.DefaultedLoopTimeout(r.ReconcileTimeout)) defer cancel() - logger := ctrl.LoggerFrom(ctx).WithName("LinodeClusterReconciler").WithValues("name", req.String()) - linodeCluster := &infrav1alpha2.LinodeCluster{} - if err := r.TracedClient().Get(ctx, req.NamespacedName, linodeCluster); err != nil { - logger.Info("Failed to fetch Linode cluster", "error", err.Error()) - - return ctrl.Result{}, client.IgnoreNotFound(err) - } + logger := ctrl.LoggerFrom(ctx).WithName("LinodeClusterReconciler").WithValues("name", linodeCluster.Name, "namespace", linodeCluster.Namespace) cluster, err := kutil.GetOwnerCluster(ctx, r.TracedClient(), linodeCluster.ObjectMeta) if err != nil { @@ -536,7 +530,7 @@ func (r *LinodeClusterReconciler) SetupWithManager(mgr ctrl.Manager, options crc Watches( &infrav1alpha2.LinodeMachine{}, handler.EnqueueRequestsFromMapFunc(linodeMachineToLinodeCluster(r.TracedClient(), mgr.GetLogger())), - ).Complete(wrappedruntimereconciler.NewRuntimeReconcilerWithTracing(r, wrappedruntimereconciler.DefaultDecorator())) + ).Complete(reconciler.AsReconcilerWithTracing(r.TracedClient(), r)) if err != nil { return fmt.Errorf("failed to build controller: %w", err) } diff --git a/internal/controller/linodecluster_controller_test.go b/internal/controller/linodecluster_controller_test.go index 7fcd50a70..6944e52a8 100644 --- a/internal/controller/linodecluster_controller_test.go +++ b/internal/controller/linodecluster_controller_test.go @@ -33,7 +33,6 @@ import ( "sigs.k8s.io/cluster-api/util/paused" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/reconcile" infrav1alpha2 "github.com/linode/cluster-api-provider-linode/api/v1alpha2" "github.com/linode/cluster-api-provider-linode/cloud/scope" @@ -299,9 +298,7 @@ var _ = Describe("cluster-lifecycle", Ordered, Label("cluster", "cluster-lifecyc }), Result("no capl cluster error", func(ctx context.Context, mck Mock) { reconciler.Client = k8sClient - _, err := reconciler.Reconcile(ctx, reconcile.Request{ - NamespacedName: client.ObjectKeyFromObject(cScope.LinodeCluster), - }) + _, err := reconciler.Reconcile(ctx, cScope.LinodeCluster) Expect(err).NotTo(HaveOccurred()) Expect(linodeCluster.Status.Ready).To(BeFalseBecause("failed to get Cluster/no-capl-cluster: clusters.cluster.x-k8s.io \"no-capl-cluster\" not found")) }), @@ -383,7 +380,7 @@ var _ = Describe("pause handling", Label("cluster", "pause"), func() { DnsClientConfig: scope.ClientConfig{Token: "test-token"}, } - _, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(linodeCluster)}) + _, err := reconciler.Reconcile(ctx, linodeCluster) Expect(err).NotTo(HaveOccurred()) Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(linodeCluster), linodeCluster)).To(Succeed()) diff --git a/internal/controller/linodefirewall_controller_helpers.go b/internal/controller/linodefirewall_controller_helpers.go index 1c57bf89f..b232b101b 100644 --- a/internal/controller/linodefirewall_controller_helpers.go +++ b/internal/controller/linodefirewall_controller_helpers.go @@ -57,7 +57,7 @@ func findObjectsForObject(logger logr.Logger, tracedClient client.Client) handle logger.Info("LinodeFirewall(s) not found for %s") return nil - case err != nil: + default: logger.Error(err, "Failed to get LinodeFirewalls") return nil diff --git a/internal/controller/linodeobjectstoragebucket_controller.go b/internal/controller/linodeobjectstoragebucket_controller.go index 782e4ae6e..f89c3eba6 100644 --- a/internal/controller/linodeobjectstoragebucket_controller.go +++ b/internal/controller/linodeobjectstoragebucket_controller.go @@ -43,7 +43,6 @@ import ( "github.com/linode/cluster-api-provider-linode/cloud/scope" "github.com/linode/cluster-api-provider-linode/cloud/services" wrappedruntimeclient "github.com/linode/cluster-api-provider-linode/observability/wrappers/runtimeclient" - wrappedruntimereconciler "github.com/linode/cluster-api-provider-linode/observability/wrappers/runtimereconciler" "github.com/linode/cluster-api-provider-linode/util" "github.com/linode/cluster-api-provider-linode/util/reconciler" ) @@ -75,20 +74,11 @@ type LinodeObjectStorageBucketReconciler struct { // // For more details, check Reconcile and its Result here: // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.17.0/pkg/reconcile -func (r *LinodeObjectStorageBucketReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *LinodeObjectStorageBucketReconciler) Reconcile(ctx context.Context, objectStorageBucket *infrav1alpha2.LinodeObjectStorageBucket) (ctrl.Result, error) { ctx, cancel := context.WithTimeout(ctx, reconciler.DefaultedLoopTimeout(r.ReconcileTimeout)) defer cancel() - logger := r.Logger.WithValues("name", req.String()) - - objectStorageBucket := &infrav1alpha2.LinodeObjectStorageBucket{} - if err := r.TracedClient().Get(ctx, req.NamespacedName, objectStorageBucket); err != nil { - if err = client.IgnoreNotFound(err); err != nil { - logger.Error(err, "Failed to fetch LinodeObjectStorageBucket", "name", req.String()) - } - - return ctrl.Result{}, err - } + logger := r.Logger.WithValues("name", objectStorageBucket.Name, "namespace", objectStorageBucket.Namespace) if _, ok := objectStorageBucket.Labels[clusterv1.ClusterNameLabel]; ok { cluster, err := kutil.GetClusterFromMetadata(ctx, r.TracedClient(), objectStorageBucket.ObjectMeta) @@ -267,7 +257,7 @@ func (r *LinodeObjectStorageBucketReconciler) SetupWithManager(mgr ctrl.Manager, &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(linodeObjectStorageBucketMapper), builder.WithPredicates(predicates.ClusterPausedTransitionsOrInfrastructureProvisioned(mgr.GetScheme(), mgr.GetLogger())), - ).Complete(wrappedruntimereconciler.NewRuntimeReconcilerWithTracing(r, wrappedruntimereconciler.DefaultDecorator())) + ).Complete(reconciler.AsReconcilerWithTracing(r.TracedClient(), r)) if err != nil { return fmt.Errorf("failed to build controller: %w", err) } diff --git a/internal/controller/linodeobjectstoragebucket_controller_test.go b/internal/controller/linodeobjectstoragebucket_controller_test.go index ce80a1265..bb1dcde55 100644 --- a/internal/controller/linodeobjectstoragebucket_controller_test.go +++ b/internal/controller/linodeobjectstoragebucket_controller_test.go @@ -327,7 +327,7 @@ var _ = Describe("errors", Label("bucket", "errors"), func() { }), Result("no error", func(ctx context.Context, mck Mock) { reconciler.Client = mck.K8sClient - _, err := reconciler.Reconcile(ctx, reconcile.Request{ + _, err := rec.AsReconcilerWithTracing(mck.K8sClient, &reconciler).Reconcile(ctx, reconcile.Request{ NamespacedName: client.ObjectKeyFromObject(bScope.Bucket), }) Expect(err).NotTo(HaveOccurred()) @@ -340,18 +340,17 @@ var _ = Describe("errors", Label("bucket", "errors"), func() { Result("error", func(ctx context.Context, mck Mock) { reconciler.Client = mck.K8sClient reconciler.Logger = bScope.Logger - _, err := reconciler.Reconcile(ctx, reconcile.Request{ + _, err := rec.AsReconcilerWithTracing(mck.K8sClient, &reconciler).Reconcile(ctx, reconcile.Request{ NamespacedName: client.ObjectKeyFromObject(bScope.Bucket), }) Expect(err.Error()).To(ContainSubstring("non-404 error")) - Expect(mck.Logs()).To(ContainSubstring("Failed to fetch LinodeObjectStorageBucket")) }), ), ), Result("scope params is missing args", func(ctx context.Context, mck Mock) { reconciler.Client = mck.K8sClient reconciler.Logger = bScope.Logger - _, err := reconciler.Reconcile(ctx, reconcile.Request{ + _, err := rec.AsReconcilerWithTracing(mck.K8sClient, &reconciler).Reconcile(ctx, reconcile.Request{ NamespacedName: client.ObjectKeyFromObject(bScope.Bucket), }) Expect(err.Error()).To(ContainSubstring("failed to create object storage bucket scope")) diff --git a/internal/controller/linodeobjectstoragekey_controller.go b/internal/controller/linodeobjectstoragekey_controller.go index 30ff68773..c7f956728 100644 --- a/internal/controller/linodeobjectstoragekey_controller.go +++ b/internal/controller/linodeobjectstoragekey_controller.go @@ -44,7 +44,6 @@ import ( "github.com/linode/cluster-api-provider-linode/cloud/scope" "github.com/linode/cluster-api-provider-linode/cloud/services" wrappedruntimeclient "github.com/linode/cluster-api-provider-linode/observability/wrappers/runtimeclient" - wrappedruntimereconciler "github.com/linode/cluster-api-provider-linode/observability/wrappers/runtimereconciler" "github.com/linode/cluster-api-provider-linode/util" "github.com/linode/cluster-api-provider-linode/util/reconciler" ) @@ -75,23 +74,14 @@ type LinodeObjectStorageKeyReconciler struct { // // For more details, check Reconcile and its Result here: // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.18.2/pkg/reconcile -func (r *LinodeObjectStorageKeyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *LinodeObjectStorageKeyReconciler) Reconcile(ctx context.Context, objectStorageKey *infrav1alpha2.LinodeObjectStorageKey) (ctrl.Result, error) { ctx, cancel := context.WithTimeout(ctx, reconciler.DefaultedLoopTimeout(r.ReconcileTimeout)) defer cancel() - logger := r.Logger.WithValues("name", req.String()) + logger := r.Logger.WithValues("name", objectStorageKey.Name, "namespace", objectStorageKey.Namespace) tracedClient := r.TracedClient() - objectStorageKey := &infrav1alpha2.LinodeObjectStorageKey{} - if err := tracedClient.Get(ctx, req.NamespacedName, objectStorageKey); err != nil { - if err = client.IgnoreNotFound(err); err != nil { - logger.Error(err, "Failed to fetch LinodeObjectStorageKey", "name", req.String()) - } - - return ctrl.Result{}, err - } - if _, ok := objectStorageKey.Labels[clusterv1.ClusterNameLabel]; ok { cluster, err := kutil.GetClusterFromMetadata(ctx, r.TracedClient(), objectStorageKey.ObjectMeta) if err != nil { @@ -348,7 +338,7 @@ func (r *LinodeObjectStorageKeyReconciler) SetupWithManager(mgr ctrl.Manager, op &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(linodeObjectStorageKeyMapper), builder.WithPredicates(predicates.ClusterPausedTransitionsOrInfrastructureProvisioned(mgr.GetScheme(), mgr.GetLogger())), - ).Complete(wrappedruntimereconciler.NewRuntimeReconcilerWithTracing(r, wrappedruntimereconciler.DefaultDecorator())) + ).Complete(reconciler.AsReconcilerWithTracing(r.TracedClient(), r)) if err != nil { return fmt.Errorf("failed to build controller: %w", err) } diff --git a/internal/controller/linodeobjectstoragekey_controller_test.go b/internal/controller/linodeobjectstoragekey_controller_test.go index 75b086048..50ec15648 100644 --- a/internal/controller/linodeobjectstoragekey_controller_test.go +++ b/internal/controller/linodeobjectstoragekey_controller_test.go @@ -38,6 +38,7 @@ import ( infrav1 "github.com/linode/cluster-api-provider-linode/api/v1alpha2" "github.com/linode/cluster-api-provider-linode/cloud/scope" "github.com/linode/cluster-api-provider-linode/mock" + utilreconciler "github.com/linode/cluster-api-provider-linode/util/reconciler" . "github.com/linode/cluster-api-provider-linode/mock/mocktest" . "github.com/onsi/ginkgo/v2" @@ -441,7 +442,7 @@ var _ = Describe("errors", Label("key", "key-errors"), func() { }), Result("no error", func(ctx context.Context, mck Mock) { reconciler.Client = mck.K8sClient - _, err := reconciler.Reconcile(ctx, reconcile.Request{ + _, err := utilreconciler.AsReconcilerWithTracing(mck.K8sClient, &reconciler).Reconcile(ctx, reconcile.Request{ NamespacedName: client.ObjectKeyFromObject(keyScope.Key), }) Expect(err).NotTo(HaveOccurred()) @@ -454,18 +455,17 @@ var _ = Describe("errors", Label("key", "key-errors"), func() { Result("error", func(ctx context.Context, mck Mock) { reconciler.Client = mck.K8sClient reconciler.Logger = keyScope.Logger - _, err := reconciler.Reconcile(ctx, reconcile.Request{ + _, err := utilreconciler.AsReconcilerWithTracing(mck.K8sClient, &reconciler).Reconcile(ctx, reconcile.Request{ NamespacedName: client.ObjectKeyFromObject(keyScope.Key), }) Expect(err.Error()).To(ContainSubstring("non-404 error")) - Expect(mck.Logs()).To(ContainSubstring("Failed to fetch LinodeObjectStorageKey")) }), ), ), Result("scope params is missing args", func(ctx context.Context, mck Mock) { reconciler.Client = mck.K8sClient reconciler.Logger = keyScope.Logger - _, err := reconciler.Reconcile(ctx, reconcile.Request{ + _, err := utilreconciler.AsReconcilerWithTracing(mck.K8sClient, &reconciler).Reconcile(ctx, reconcile.Request{ NamespacedName: client.ObjectKeyFromObject(keyScope.Key), }) Expect(err.Error()).To(ContainSubstring("failed to create object storage key scope")) diff --git a/internal/controller/linodeplacementgroup_controller.go b/internal/controller/linodeplacementgroup_controller.go index 29f22b024..e44591811 100644 --- a/internal/controller/linodeplacementgroup_controller.go +++ b/internal/controller/linodeplacementgroup_controller.go @@ -45,7 +45,6 @@ import ( infrav1alpha2 "github.com/linode/cluster-api-provider-linode/api/v1alpha2" "github.com/linode/cluster-api-provider-linode/cloud/scope" wrappedruntimeclient "github.com/linode/cluster-api-provider-linode/observability/wrappers/runtimeclient" - wrappedruntimereconciler "github.com/linode/cluster-api-provider-linode/observability/wrappers/runtimereconciler" "github.com/linode/cluster-api-provider-linode/util" "github.com/linode/cluster-api-provider-linode/util/reconciler" ) @@ -69,20 +68,12 @@ type LinodePlacementGroupReconciler struct { // move the current state of the Placement Group closer to the desired state. // -func (r *LinodePlacementGroupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *LinodePlacementGroupReconciler) Reconcile(ctx context.Context, linodeplacementgroup *infrav1alpha2.LinodePlacementGroup) (ctrl.Result, error) { ctx, cancel := context.WithTimeout(ctx, reconciler.DefaultedLoopTimeout(r.ReconcileTimeout)) defer cancel() - log := ctrl.LoggerFrom(ctx).WithName("LinodePlacementGroupReconciler").WithValues("name", req.String()) + log := ctrl.LoggerFrom(ctx).WithName("LinodePlacementGroupReconciler").WithValues("name", linodeplacementgroup.Name, "namespace", linodeplacementgroup.Namespace) - linodeplacementgroup := &infrav1alpha2.LinodePlacementGroup{} - if err := r.TracedClient().Get(ctx, req.NamespacedName, linodeplacementgroup); err != nil { - if err = client.IgnoreNotFound(err); err != nil { - log.Error(err, "Failed to fetch LinodePlacementGroup") - } - - return ctrl.Result{}, err - } var cluster *clusterv1.Cluster var err error if _, ok := linodeplacementgroup.Labels[clusterv1.ClusterNameLabel]; ok { @@ -412,7 +403,7 @@ func (r *LinodePlacementGroupReconciler) SetupWithManager(mgr ctrl.Manager, opti &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(linodePlacementGroupMapper), builder.WithPredicates(predicates.ClusterPausedTransitionsOrInfrastructureProvisioned(mgr.GetScheme(), mgr.GetLogger())), - ).Complete(wrappedruntimereconciler.NewRuntimeReconcilerWithTracing(r, wrappedruntimereconciler.DefaultDecorator())) + ).Complete(reconciler.AsReconcilerWithTracing(r.TracedClient(), r)) if err != nil { return fmt.Errorf("failed to build controller: %w", err) } diff --git a/internal/controller/linodeplacementgroup_controller_test.go b/internal/controller/linodeplacementgroup_controller_test.go index 902b0b9b8..fa608da16 100644 --- a/internal/controller/linodeplacementgroup_controller_test.go +++ b/internal/controller/linodeplacementgroup_controller_test.go @@ -31,7 +31,6 @@ import ( "sigs.k8s.io/cluster-api/util/paused" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/reconcile" infrav1alpha2 "github.com/linode/cluster-api-provider-linode/api/v1alpha2" "github.com/linode/cluster-api-provider-linode/cloud/scope" @@ -270,7 +269,7 @@ var _ = Describe("pause handling", Label("placementgroup", "pause"), func() { LinodeClientConfig: scope.ClientConfig{Token: "test-token"}, } - _, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(placementGroup)}) + _, err := reconciler.Reconcile(ctx, placementGroup) Expect(err).NotTo(HaveOccurred()) Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(placementGroup), placementGroup)).To(Succeed()) diff --git a/internal/controller/linodevpc_controller.go b/internal/controller/linodevpc_controller.go index 9003a62b8..cdc3da9e1 100644 --- a/internal/controller/linodevpc_controller.go +++ b/internal/controller/linodevpc_controller.go @@ -46,7 +46,6 @@ import ( infrav1alpha2 "github.com/linode/cluster-api-provider-linode/api/v1alpha2" "github.com/linode/cluster-api-provider-linode/cloud/scope" wrappedruntimeclient "github.com/linode/cluster-api-provider-linode/observability/wrappers/runtimeclient" - wrappedruntimereconciler "github.com/linode/cluster-api-provider-linode/observability/wrappers/runtimereconciler" "github.com/linode/cluster-api-provider-linode/util" "github.com/linode/cluster-api-provider-linode/util/reconciler" ) @@ -77,18 +76,11 @@ type LinodeVPCReconciler struct { // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.16.0/pkg/reconcile // -func (r *LinodeVPCReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *LinodeVPCReconciler) Reconcile(ctx context.Context, linodeVPC *infrav1alpha2.LinodeVPC) (ctrl.Result, error) { ctx, cancel := context.WithTimeout(ctx, reconciler.DefaultedLoopTimeout(r.ReconcileTimeout)) defer cancel() - log := ctrl.LoggerFrom(ctx).WithName("LinodeVPCReconciler").WithValues("name", req.String()) - linodeVPC := &infrav1alpha2.LinodeVPC{} - if err := r.TracedClient().Get(ctx, req.NamespacedName, linodeVPC); err != nil { - if err = client.IgnoreNotFound(err); err != nil { - log.Error(err, "Failed to fetch LinodeVPC") - } - return ctrl.Result{}, err - } + log := ctrl.LoggerFrom(ctx).WithName("LinodeVPCReconciler").WithValues("name", linodeVPC.Name, "namespace", linodeVPC.Namespace) var cluster *clusterv1.Cluster var err error @@ -527,7 +519,7 @@ func (r *LinodeVPCReconciler) SetupWithManager(mgr ctrl.Manager, options crcontr &clusterv1.Cluster{}, handler.EnqueueRequestsFromMapFunc(linodeVPCMapper), builder.WithPredicates(predicates.ClusterPausedTransitionsOrInfrastructureProvisioned(mgr.GetScheme(), mgr.GetLogger())), - ).Complete(wrappedruntimereconciler.NewRuntimeReconcilerWithTracing(r, wrappedruntimereconciler.DefaultDecorator())) + ).Complete(reconciler.AsReconcilerWithTracing(r.TracedClient(), r)) if err != nil { return fmt.Errorf("failed to build controller: %w", err) } diff --git a/internal/controller/linodevpc_controller_test.go b/internal/controller/linodevpc_controller_test.go index 2d977f263..8b2f84e33 100644 --- a/internal/controller/linodevpc_controller_test.go +++ b/internal/controller/linodevpc_controller_test.go @@ -31,7 +31,6 @@ import ( "sigs.k8s.io/cluster-api/util/paused" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/reconcile" infrav1alpha2 "github.com/linode/cluster-api-provider-linode/api/v1alpha2" "github.com/linode/cluster-api-provider-linode/cloud/scope" @@ -338,7 +337,7 @@ var _ = Describe("pause handling", Label("vpc", "pause"), func() { LinodeClientConfig: scope.ClientConfig{Token: "test-token"}, } - _, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(vpc)}) + _, err := reconciler.Reconcile(ctx, vpc) Expect(err).NotTo(HaveOccurred()) Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(vpc), vpc)).To(Succeed()) diff --git a/util/reconciler/typedreconciler.go b/util/reconciler/typedreconciler.go new file mode 100644 index 000000000..1d60e3efb --- /dev/null +++ b/util/reconciler/typedreconciler.go @@ -0,0 +1,39 @@ +package reconciler + +import ( + "context" + + clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + o11yreconciler "github.com/linode/cluster-api-provider-linode/observability/wrappers/runtimereconciler" +) + +func AsReconcilerWithTracing[object client.Object](k8sClient client.Client, rec reconcile.ObjectReconciler[object]) reconcile.Reconciler { + capiReconciler := &capiReconcilerAdapter[object]{ + objReconciler: rec, + k8sClient: k8sClient, + } + + return o11yreconciler.NewRuntimeReconcilerWithTracing( + reconcile.AsReconciler( + k8sClient, capiReconciler), + o11yreconciler.DefaultDecorator()) +} + +type capiReconcilerAdapter[object client.Object] struct { + objReconciler reconcile.ObjectReconciler[object] + k8sClient client.Client +} + +func (a *capiReconcilerAdapter[object]) Reconcile(ctx context.Context, obj object) (reconcile.Result, error) { + // Skip normal reconciliation when clusterctl marks the object for deletion during a move. + // Reconciling here could recreate or mutate infrastructure while ownership is being handed off. + if annotations := obj.GetAnnotations(); annotations != nil { + if _, exists := annotations[clusterctlv1.DeleteForMoveAnnotation]; exists { + return reconcile.Result{}, nil + } + } + return a.objReconciler.Reconcile(ctx, obj) +}