Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/pr-semantics.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ jobs:
docs
release
testdata
standalone
replication
sentinel
cluster
ignoreLabels: |
bot
ignore-semantic-pull-request
Expand Down
1 change: 1 addition & 0 deletions pkg/controllers/rediscluster/rediscluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
return intctrlutil.Reconciled()
}
if _, found := instance.ObjectMeta.GetAnnotations()["rediscluster.opstreelabs.in/skip-reconcile"]; found {
log.FromContext(ctx).Info("found skip reconcile annotation", "namespace", instance.Namespace, "name", instance.Name)
return intctrlutil.RequeueAfter(ctx, time.Second*10, "found skip reconcile annotation")
}
instance.SetDefault()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ func (r *Reconciler) reconcileFinalizer(ctx context.Context, instance *redisv1be

func (r *Reconciler) reconcileAnnotation(ctx context.Context, instance *redisv1beta2.RedisReplication) (ctrl.Result, error) {
if _, found := instance.ObjectMeta.GetAnnotations()["redisreplication.opstreelabs.in/skip-reconcile"]; found {
log.FromContext(ctx).Info("found skip reconcile annotation", "namespace", instance.Namespace, "name", instance.Name)
return intctrlutil.RequeueAfter(ctx, time.Second*10, "found skip reconcile annotation")
}
return intctrlutil.Reconciled()
Expand Down
98 changes: 73 additions & 25 deletions pkg/controllers/redissentinel/redissentinel_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,43 +13,84 @@ import (
"k8s.io/client-go/kubernetes"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
)

// RedisSentinelReconciler reconciles a RedisSentinel object
type RedisSentinelReconciler struct {
client.Client
K8sClient kubernetes.Interface
Dk8sClient dynamic.Interface
Scheme *runtime.Scheme

K8sClient kubernetes.Interface
Dk8sClient dynamic.Interface
Scheme *runtime.Scheme
ReplicationWatcher *intctrlutil.ResourceWatcher
}

func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
instance := &redisv1beta2.RedisSentinel{}

err := r.Client.Get(context.TODO(), req.NamespacedName, instance)
err := r.Client.Get(ctx, req.NamespacedName, instance)
if err != nil {
return intctrlutil.RequeueWithErrorChecking(ctx, err, "")
return intctrlutil.RequeueWithErrorChecking(ctx, err, "failed to get RedisSentinel instance")
}
if instance.ObjectMeta.GetDeletionTimestamp() != nil {
if err = k8sutils.HandleRedisSentinelFinalizer(ctx, r.Client, instance); err != nil {
return intctrlutil.RequeueWithError(ctx, err, "")

var reconcilers []reconciler
if k8sutils.IsDeleted(instance) {
reconcilers = []reconciler{
{typ: "finalizer", rec: r.reconcileFinalizer},
}
} else {
reconcilers = []reconciler{
{typ: "annotation", rec: r.reconcileAnnotation},
{typ: "finalizer", rec: r.reconcileFinalizer},
{typ: "replication", rec: r.reconcileReplication},
{typ: "sentinel", rec: r.reconcileSentinel},
{typ: "pdb", rec: r.reconcilePDB},
{typ: "service", rec: r.reconcileService},
}
return intctrlutil.Reconciled()
}

if _, found := instance.ObjectMeta.GetAnnotations()["redissentinel.opstreelabs.in/skip-reconcile"]; found {
return intctrlutil.RequeueAfter(ctx, time.Second*10, "found skip reconcile annotation")
for _, reconciler := range reconcilers {
result, err := reconciler.rec(ctx, instance)
if err != nil {
return intctrlutil.RequeueWithError(ctx, err, "")
}
if result.Requeue {
return result, nil
}
}

// Get total Sentinel Replicas
// sentinelReplicas := instance.Spec.GetSentinelCounts("sentinel")
// DO NOT REQUEUE.
// only reconcile on resource(sentinel && watched redis replication) changes
return intctrlutil.Reconciled()
}

if err = k8sutils.AddFinalizer(ctx, instance, k8sutils.RedisSentinelFinalizer, r.Client); err != nil {
type reconciler struct {
typ string
rec func(ctx context.Context, instance *redisv1beta2.RedisSentinel) (ctrl.Result, error)
}

func (r *RedisSentinelReconciler) reconcileFinalizer(ctx context.Context, instance *redisv1beta2.RedisSentinel) (ctrl.Result, error) {
if k8sutils.IsDeleted(instance) {
if err := k8sutils.HandleRedisSentinelFinalizer(ctx, r.Client, instance); err != nil {
return intctrlutil.RequeueWithError(ctx, err, "")
}
return intctrlutil.Reconciled()
}
if err := k8sutils.AddFinalizer(ctx, instance, k8sutils.RedisSentinelFinalizer, r.Client); err != nil {
return intctrlutil.RequeueWithError(ctx, err, "")
}
return intctrlutil.Reconciled()
}

func (r *RedisSentinelReconciler) reconcileAnnotation(ctx context.Context, instance *redisv1beta2.RedisSentinel) (ctrl.Result, error) {
if _, found := instance.ObjectMeta.GetAnnotations()["redissentinel.opstreelabs.in/skip-reconcile"]; found {
log.FromContext(ctx).Info("found skip reconcile annotation", "namespace", instance.Namespace, "name", instance.Name)
return intctrlutil.RequeueAfter(ctx, time.Second*10, "found skip reconcile annotation")
}
return intctrlutil.Reconciled()
}

func (r *RedisSentinelReconciler) reconcileReplication(ctx context.Context, instance *redisv1beta2.RedisSentinel) (ctrl.Result, error) {
if instance.Spec.RedisSentinelConfig != nil && !k8sutils.IsRedisReplicationReady(ctx, r.K8sClient, r.Dk8sClient, instance) {
return intctrlutil.RequeueAfter(ctx, time.Second*10, "Redis Replication is specified but not ready")
}
Expand All @@ -58,27 +99,34 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques
r.ReplicationWatcher.Watch(
ctx,
types.NamespacedName{
Namespace: req.Namespace,
Namespace: instance.Namespace,
Name: instance.Spec.RedisSentinelConfig.RedisReplicationName,
},
req.NamespacedName,
types.NamespacedName{
Namespace: instance.Namespace,
Name: instance.Name,
},
)
}
return intctrlutil.Reconciled()
}

// Create Redis Sentinel
err = k8sutils.CreateRedisSentinel(ctx, r.K8sClient, instance, r.K8sClient, r.Dk8sClient)
if err != nil {
func (r *RedisSentinelReconciler) reconcileSentinel(ctx context.Context, instance *redisv1beta2.RedisSentinel) (ctrl.Result, error) {
if err := k8sutils.CreateRedisSentinel(ctx, r.K8sClient, instance, r.K8sClient, r.Dk8sClient); err != nil {
return intctrlutil.RequeueWithError(ctx, err, "")
}
return intctrlutil.Reconciled()
}

err = k8sutils.ReconcileSentinelPodDisruptionBudget(ctx, instance, instance.Spec.PodDisruptionBudget, r.K8sClient)
if err != nil {
func (r *RedisSentinelReconciler) reconcilePDB(ctx context.Context, instance *redisv1beta2.RedisSentinel) (ctrl.Result, error) {
if err := k8sutils.ReconcileSentinelPodDisruptionBudget(ctx, instance, instance.Spec.PodDisruptionBudget, r.K8sClient); err != nil {
return intctrlutil.RequeueWithError(ctx, err, "")
}
return intctrlutil.Reconciled()
}

// Create the Service for Redis Sentinel
err = k8sutils.CreateRedisSentinelService(ctx, instance, r.K8sClient)
if err != nil {
func (r *RedisSentinelReconciler) reconcileService(ctx context.Context, instance *redisv1beta2.RedisSentinel) (ctrl.Result, error) {
if err := k8sutils.CreateRedisSentinelService(ctx, instance, r.K8sClient); err != nil {
return intctrlutil.RequeueWithError(ctx, err, "")
}
return intctrlutil.Reconciled()
Expand Down