reduce code duplication

This commit is contained in:
Luca Burgazzoli 2024-05-18 09:06:38 +02:00
parent 53e52ba39a
commit a9fb58794a
No known key found for this signature in database
GPG Key ID: 238C46A40510C1A9
5 changed files with 118 additions and 100 deletions

View File

@ -20,6 +20,8 @@ import (
"context" "context"
"fmt" "fmt"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/openshift" "github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/openshift"
"github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/helm" "github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/helm"
@ -50,7 +52,7 @@ func NewReconciler(ctx context.Context, manager ctrlRt.Manager, o helm.Options)
rec := Reconciler{} rec := Reconciler{}
rec.l = ctrlRt.Log.WithName("dapr-controlplane-controller") rec.l = ctrlRt.Log.WithName("dapr-controlplane-controller")
rec.Client = c rec.client = c
rec.Scheme = manager.GetScheme() rec.Scheme = manager.GetScheme()
rec.ClusterType = controller.ClusterTypeVanilla rec.ClusterType = controller.ClusterTypeVanilla
rec.manager = manager rec.manager = manager
@ -94,8 +96,7 @@ func NewReconciler(ctx context.Context, manager ctrlRt.Manager, o helm.Options)
// +kubebuilder:rbac:groups=operator.dapr.io,resources=daprinstances/status,verbs=get // +kubebuilder:rbac:groups=operator.dapr.io,resources=daprinstances/status,verbs=get
type Reconciler struct { type Reconciler struct {
*client.Client client *client.Client
Scheme *runtime.Scheme Scheme *runtime.Scheme
ClusterType controller.ClusterType ClusterType controller.ClusterType
actions []Action actions []Action
@ -106,6 +107,10 @@ type Reconciler struct {
recorder record.EventRecorder recorder record.EventRecorder
} }
func (r *Reconciler) Client() *client.Client {
return r.client
}
func (r *Reconciler) init(ctx context.Context) error { func (r *Reconciler) init(ctx context.Context) error {
c := ctrlRt.NewControllerManagedBy(r.manager) c := ctrlRt.NewControllerManagedBy(r.manager)
@ -115,7 +120,7 @@ func (r *Reconciler) init(ctx context.Context) error {
))) )))
for i := range r.actions { for i := range r.actions {
b, err := r.actions[i].Configure(ctx, r.Client, c) b, err := r.actions[i].Configure(ctx, r.Client(), c)
if err != nil { if err != nil {
//nolint:wrapcheck //nolint:wrapcheck
return err return err
@ -124,7 +129,9 @@ func (r *Reconciler) init(ctx context.Context) error {
c = b c = b
} }
ct, err := c.Build(r) objRec := reconcile.AsReconciler[*daprApi.DaprControlPlane](r.manager.GetClient(), r)
ct, err := c.Build(objRec)
if err != nil { if err != nil {
return fmt.Errorf("failure building the application controller for DaprControlPlane resource: %w", err) return fmt.Errorf("failure building the application controller for DaprControlPlane resource: %w", err)
} }

View File

@ -23,6 +23,8 @@ import (
"os" "os"
"sort" "sort"
"github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/controller/reconciler"
"github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/controller" "github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/controller"
"github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/conditions" "github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/conditions"
@ -32,34 +34,26 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime" ctrl "sigs.k8s.io/controller-runtime"
ctrlutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log"
daprvApi "github.com/dapr-sandbox/dapr-kubernetes-operator/api/operator/v1alpha1" daprApi "github.com/dapr-sandbox/dapr-kubernetes-operator/api/operator/v1alpha1"
) )
func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { func (r *Reconciler) Reconcile(ctx context.Context, res *daprApi.DaprControlPlane) (ctrl.Result, error) {
l := log.FromContext(ctx) l := log.FromContext(ctx)
l.Info("Reconciling", "resource", req.NamespacedName.String())
rr := ReconciliationRequest{ rr := ReconciliationRequest{
Client: r.Client, Client: r.Client(),
NamespacedName: types.NamespacedName{ NamespacedName: types.NamespacedName{
Name: req.Name, Name: res.Name,
Namespace: req.Namespace, Namespace: res.Namespace,
}, },
ClusterType: r.ClusterType, ClusterType: r.ClusterType,
Reconciler: r, Reconciler: r,
Resource: &daprvApi.DaprControlPlane{}, Resource: res,
} }
err := r.Get(ctx, req.NamespacedName, rr.Resource) l.Info("Reconciling", "resource", rr.NamespacedName.String())
if err != nil {
if k8serrors.IsNotFound(err) {
// no CR found anymore, maybe deleted
return ctrl.Result{}, nil
}
}
// by default, the controller expect the DaprControlPlane resource to be created // by default, the controller expect the DaprControlPlane resource to be created
// in the same namespace where it runs, if not fallback to the default namespace // in the same namespace where it runs, if not fallback to the default namespace
@ -69,7 +63,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
ns = controller.NamespaceDefault ns = controller.NamespaceDefault
} }
if req.Name != DaprControlPlaneResourceName || req.Namespace != ns { if res.Name != DaprControlPlaneResourceName || res.Namespace != ns {
rr.Resource.Status.Phase = conditions.TypeError rr.Resource.Status.Phase = conditions.TypeError
meta.SetStatusCondition(&rr.Resource.Status.Conditions, metav1.Condition{ meta.SetStatusCondition(&rr.Resource.Status.Conditions, metav1.Condition{
@ -82,7 +76,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
ns), ns),
}) })
err = r.Status().Update(ctx, rr.Resource) err := r.Client().Status().Update(ctx, rr.Resource)
if err != nil && k8serrors.IsConflict(err) { if err != nil && k8serrors.IsConflict(err) {
l.Info(err.Error()) l.Info(err.Error())
@ -92,42 +86,23 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
return ctrl.Result{}, fmt.Errorf("error updating DaprControlPlane resource: %w", err) return ctrl.Result{}, fmt.Errorf("error updating DaprControlPlane resource: %w", err)
} }
//nolint:nestif //nolint:wrapcheck
if rr.Resource.ObjectMeta.DeletionTimestamp.IsZero() { if rr.Resource.ObjectMeta.DeletionTimestamp.IsZero() {
// err := reconciler.AddFinalizer(ctx, r.Client(), rr.Resource, DaprControlPlaneFinalizerName)
// Add finalizer if err != nil {
// return ctrl.Result{}, err
if ctrlutil.AddFinalizer(rr.Resource, DaprControlPlaneFinalizerName) {
if err := r.Update(ctx, rr.Resource); err != nil {
if k8serrors.IsConflict(err) {
return ctrl.Result{}, fmt.Errorf("conflict when adding finalizer to %s: %w", req.NamespacedName, err)
}
return ctrl.Result{}, fmt.Errorf("failure adding finalizer to %s: %w", req.NamespacedName, err)
}
} }
} else { } else {
//
// Cleanup leftovers if needed // Cleanup leftovers if needed
//
for i := len(r.actions) - 1; i >= 0; i-- { for i := len(r.actions) - 1; i >= 0; i-- {
if err := r.actions[i].Cleanup(ctx, &rr); err != nil { if err := r.actions[i].Cleanup(ctx, &rr); err != nil {
//nolint:wrapcheck
return ctrl.Result{}, err return ctrl.Result{}, err
} }
} }
// err := reconciler.RemoveFinalizer(ctx, r.Client(), rr.Resource, DaprControlPlaneFinalizerName)
// Handle finalizer if err != nil {
// return ctrl.Result{}, err
if ctrlutil.RemoveFinalizer(rr.Resource, DaprControlPlaneFinalizerName) {
if err := r.Update(ctx, rr.Resource); err != nil {
if k8serrors.IsConflict(err) {
return ctrl.Result{}, fmt.Errorf("conflict when removing finalizer to %s: %w", req.NamespacedName, err)
}
return ctrl.Result{}, fmt.Errorf("failure removing finalizer from %s: %w", req.NamespacedName, err)
}
} }
return ctrl.Result{}, nil return ctrl.Result{}, nil
@ -174,7 +149,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
// Update status // Update status
// //
err = r.Status().Update(ctx, rr.Resource) err := r.Client().Status().Update(ctx, rr.Resource)
if err != nil && k8serrors.IsConflict(err) { if err != nil && k8serrors.IsConflict(err) {
l.Info(err.Error()) l.Info(err.Error())
return ctrl.Result{Requeue: true}, nil return ctrl.Result{Requeue: true}, nil

View File

@ -37,7 +37,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/predicate"
daprvApi "github.com/dapr-sandbox/dapr-kubernetes-operator/api/operator/v1alpha1" daprApi "github.com/dapr-sandbox/dapr-kubernetes-operator/api/operator/v1alpha1"
"github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/controller" "github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/controller"
"github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/controller/client" "github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/controller/client"
"github.com/go-logr/logr" "github.com/go-logr/logr"
@ -56,7 +56,7 @@ func NewReconciler(ctx context.Context, manager ctrlRt.Manager, o helm.Options)
rec := Reconciler{} rec := Reconciler{}
rec.l = ctrlRt.Log.WithName("dapr-instance-controller") rec.l = ctrlRt.Log.WithName("dapr-instance-controller")
rec.Client = c rec.client = c
rec.Scheme = manager.GetScheme() rec.Scheme = manager.GetScheme()
rec.ClusterType = controller.ClusterTypeVanilla rec.ClusterType = controller.ClusterTypeVanilla
rec.manager = manager rec.manager = manager
@ -126,8 +126,7 @@ func NewReconciler(ctx context.Context, manager ctrlRt.Manager, o helm.Options)
// +kubebuilder:rbac:groups=dapr.io,resources=subscriptions/finalizers,verbs=* // +kubebuilder:rbac:groups=dapr.io,resources=subscriptions/finalizers,verbs=*
type Reconciler struct { type Reconciler struct {
*client.Client client *client.Client
Scheme *runtime.Scheme Scheme *runtime.Scheme
ClusterType controller.ClusterType ClusterType controller.ClusterType
actions []Action actions []Action
@ -138,16 +137,20 @@ type Reconciler struct {
recorder record.EventRecorder recorder record.EventRecorder
} }
func (r *Reconciler) Client() *client.Client {
return r.client
}
func (r *Reconciler) init(ctx context.Context) error { func (r *Reconciler) init(ctx context.Context) error {
c := ctrlRt.NewControllerManagedBy(r.manager) c := ctrlRt.NewControllerManagedBy(r.manager)
c = c.For(&daprvApi.DaprInstance{}, builder.WithPredicates( c = c.For(&daprApi.DaprInstance{}, builder.WithPredicates(
predicate.Or( predicate.Or(
predicate.GenerationChangedPredicate{}, predicate.GenerationChangedPredicate{},
))) )))
for i := range r.actions { for i := range r.actions {
b, err := r.actions[i].Configure(ctx, r.Client, c) b, err := r.actions[i].Configure(ctx, r.Client(), c)
if err != nil { if err != nil {
//nolint:wrapcheck //nolint:wrapcheck
return err return err
@ -156,7 +159,9 @@ func (r *Reconciler) init(ctx context.Context) error {
c = b c = b
} }
ct, err := c.Build(r) objRec := reconcile.AsReconciler[*daprApi.DaprInstance](r.manager.GetClient(), r)
ct, err := c.Build(objRec)
if err != nil { if err != nil {
return fmt.Errorf("failure building the application controller for DaprInstance resource: %w", err) return fmt.Errorf("failure building the application controller for DaprInstance resource: %w", err)
} }

View File

@ -23,6 +23,8 @@ import (
"os" "os"
"sort" "sort"
"github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/controller/reconciler"
"github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/controller" "github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/controller"
"github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/conditions" "github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/conditions"
@ -32,25 +34,23 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime" ctrl "sigs.k8s.io/controller-runtime"
ctrlutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log"
daprvApi "github.com/dapr-sandbox/dapr-kubernetes-operator/api/operator/v1alpha1" daprApi "github.com/dapr-sandbox/dapr-kubernetes-operator/api/operator/v1alpha1"
) )
func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { func (r *Reconciler) Reconcile(ctx context.Context, res *daprApi.DaprInstance) (ctrl.Result, error) {
l := log.FromContext(ctx) l := log.FromContext(ctx)
l.Info("Reconciling", "resource", req.NamespacedName.String())
rr := ReconciliationRequest{ rr := ReconciliationRequest{
Client: r.Client, Client: r.Client(),
NamespacedName: types.NamespacedName{ NamespacedName: types.NamespacedName{
Name: req.Name, Name: res.Name,
Namespace: req.Namespace, Namespace: res.Namespace,
}, },
ClusterType: r.ClusterType, ClusterType: r.ClusterType,
Reconciler: r, Reconciler: r,
Resource: &daprvApi.DaprInstance{}, Resource: res,
Chart: r.c, Chart: r.c,
Overrides: map[string]interface{}{ Overrides: map[string]interface{}{
"dapr_operator": map[string]interface{}{"runAsNonRoot": "true"}, "dapr_operator": map[string]interface{}{"runAsNonRoot": "true"},
@ -60,13 +60,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
}, },
} }
err := r.Get(ctx, req.NamespacedName, rr.Resource) l.Info("Reconciling", "resource", rr.NamespacedName.String())
if err != nil {
if k8serrors.IsNotFound(err) {
// no CR found anymore, maybe deleted
return ctrl.Result{}, nil
}
}
// by default, the controller expect the DaprInstance resource to be created // by default, the controller expect the DaprInstance resource to be created
// in the same namespace where it runs, if not fallback to the default namespace // in the same namespace where it runs, if not fallback to the default namespace
@ -76,7 +70,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
ns = controller.NamespaceDefault ns = controller.NamespaceDefault
} }
if req.Name != DaprInstanceResourceName || req.Namespace != ns { if res.Name != DaprInstanceResourceName || res.Namespace != ns {
rr.Resource.Status.Phase = conditions.TypeError rr.Resource.Status.Phase = conditions.TypeError
meta.SetStatusCondition(&rr.Resource.Status.Conditions, metav1.Condition{ meta.SetStatusCondition(&rr.Resource.Status.Conditions, metav1.Condition{
@ -89,7 +83,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
ns), ns),
}) })
err = r.Status().Update(ctx, rr.Resource) err := r.Client().Status().Update(ctx, rr.Resource)
if err != nil && k8serrors.IsConflict(err) { if err != nil && k8serrors.IsConflict(err) {
l.Info(err.Error()) l.Info(err.Error())
@ -99,42 +93,23 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
return ctrl.Result{}, fmt.Errorf("error updating DaprInstance resource: %w", err) return ctrl.Result{}, fmt.Errorf("error updating DaprInstance resource: %w", err)
} }
//nolint:nestif //nolint:wrapcheck
if rr.Resource.ObjectMeta.DeletionTimestamp.IsZero() { if rr.Resource.ObjectMeta.DeletionTimestamp.IsZero() {
// err := reconciler.AddFinalizer(ctx, r.Client(), rr.Resource, DaprInstanceFinalizerName)
// Add finalizer if err != nil {
// return ctrl.Result{}, err
if ctrlutil.AddFinalizer(rr.Resource, DaprInstanceFinalizerName) {
if err := r.Update(ctx, rr.Resource); err != nil {
if k8serrors.IsConflict(err) {
return ctrl.Result{}, fmt.Errorf("conflict when adding finalizer to %s: %w", req.NamespacedName, err)
}
return ctrl.Result{}, fmt.Errorf("failure adding finalizer to %s: %w", req.NamespacedName, err)
}
} }
} else { } else {
//
// Cleanup leftovers if needed // Cleanup leftovers if needed
//
for i := len(r.actions) - 1; i >= 0; i-- { for i := len(r.actions) - 1; i >= 0; i-- {
if err := r.actions[i].Cleanup(ctx, &rr); err != nil { if err := r.actions[i].Cleanup(ctx, &rr); err != nil {
//nolint:wrapcheck
return ctrl.Result{}, err return ctrl.Result{}, err
} }
} }
// err := reconciler.RemoveFinalizer(ctx, r.Client(), rr.Resource, DaprInstanceFinalizerName)
// Handle finalizer if err != nil {
// return ctrl.Result{}, err
if ctrlutil.RemoveFinalizer(rr.Resource, DaprInstanceFinalizerName) {
if err := r.Update(ctx, rr.Resource); err != nil {
if k8serrors.IsConflict(err) {
return ctrl.Result{}, fmt.Errorf("conflict when removing finalizer to %s: %w", req.NamespacedName, err)
}
return ctrl.Result{}, fmt.Errorf("failure removing finalizer from %s: %w", req.NamespacedName, err)
}
} }
return ctrl.Result{}, nil return ctrl.Result{}, nil
@ -181,7 +156,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
// Update status // Update status
// //
err = r.Status().Update(ctx, rr.Resource) err := r.Client().Status().Update(ctx, rr.Resource)
if err != nil && k8serrors.IsConflict(err) { if err != nil && k8serrors.IsConflict(err) {
l.Info(err.Error()) l.Info(err.Error())

View File

@ -0,0 +1,56 @@
package reconciler
import (
"context"
"fmt"
"github.com/dapr-sandbox/dapr-kubernetes-operator/pkg/controller/client"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
"sigs.k8s.io/controller-runtime/pkg/builder"
ctrlClient "sigs.k8s.io/controller-runtime/pkg/client"
ctrlutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)
type Reconciler interface {
Client() *client.Client
}
type Action[T any] interface {
Configure(ctx context.Context, c *client.Client, b *builder.Builder) (*builder.Builder, error)
Run(ctx context.Context, rc *T) error
Cleanup(ctx context.Context, rc *T) error
}
func AddFinalizer(ctx context.Context, client ctrlClient.Client, o ctrlClient.Object, name string) error {
if !ctrlutil.AddFinalizer(o, name) {
return nil
}
err := client.Update(ctx, o)
if k8serrors.IsConflict(err) {
return fmt.Errorf("conflict when adding finalizer to %s/%s: %w", o.GetNamespace(), o.GetName(), err)
}
if err != nil {
return fmt.Errorf("failure adding finalizer to %s/%s: %w", o.GetNamespace(), o.GetName(), err)
}
return nil
}
func RemoveFinalizer(ctx context.Context, client ctrlClient.Client, o ctrlClient.Object, name string) error {
if !ctrlutil.RemoveFinalizer(o, name) {
return nil
}
err := client.Update(ctx, o)
if k8serrors.IsConflict(err) {
return fmt.Errorf("conflict when removing finalizer to %s/%s: %w", o.GetNamespace(), o.GetName(), err)
}
if err != nil {
return fmt.Errorf("failure removing finalizer from %s/%s: %w", o.GetNamespace(), o.GetName(), err)
}
return nil
}