Skip to content

Commit c48c9c5

Browse files
authored
feat: reconcile redis sentinel only on master changed (#1122)
* feat: redissentinel reconcile only on master changed Signed-off-by: drivebyer <[email protected]> * fix Lint Signed-off-by: drivebyer <[email protected]> * e2e cleanup Signed-off-by: drivebyer <[email protected]> --------- Signed-off-by: drivebyer <[email protected]>
1 parent e6f354f commit c48c9c5

35 files changed

+161
-683
lines changed

example/v1beta2/redis-replication.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ spec:
2020
limits:
2121
cpu: 101m
2222
memory: 128Mi
23-
redisSecret:
24-
name: redis-secret
25-
key: password
23+
# redisSecret:
24+
# name: redis-secret
25+
# key: password
2626
# imagePullSecrets:
2727
# - name: regcred
2828
redisExporter:

main.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/OT-CONTAINER-KIT/redis-operator/pkg/controllers/rediscluster"
2828
"github.com/OT-CONTAINER-KIT/redis-operator/pkg/controllers/redisreplication"
2929
"github.com/OT-CONTAINER-KIT/redis-operator/pkg/controllers/redissentinel"
30+
intctrlutil "github.com/OT-CONTAINER-KIT/redis-operator/pkg/controllerutil"
3031
"github.com/OT-CONTAINER-KIT/redis-operator/pkg/k8sutils"
3132
"k8s.io/apimachinery/pkg/runtime"
3233
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
@@ -153,11 +154,12 @@ func main() {
153154
os.Exit(1)
154155
}
155156
if err = (&redissentinel.RedisSentinelReconciler{
156-
Client: mgr.GetClient(),
157-
K8sClient: k8sclient,
158-
Dk8sClient: dk8sClient,
159-
Log: ctrl.Log.WithName("controllers").WithName("RedisSentinel"),
160-
Scheme: mgr.GetScheme(),
157+
Client: mgr.GetClient(),
158+
K8sClient: k8sclient,
159+
Dk8sClient: dk8sClient,
160+
Log: ctrl.Log.WithName("controllers").WithName("RedisSentinel"),
161+
Scheme: mgr.GetScheme(),
162+
ReplicationWatcher: intctrlutil.NewResourceWatcher(),
161163
}).SetupWithManager(mgr); err != nil {
162164
setupLog.Error(err, "unable to create controller", "controller", "RedisSentinel")
163165
os.Exit(1)

pkg/controllers/redissentinel/redissentinel_controller.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/OT-CONTAINER-KIT/redis-operator/pkg/k8sutils"
1010
"github.com/go-logr/logr"
1111
"k8s.io/apimachinery/pkg/runtime"
12+
"k8s.io/apimachinery/pkg/types"
1213
"k8s.io/client-go/dynamic"
1314
"k8s.io/client-go/kubernetes"
1415
ctrl "sigs.k8s.io/controller-runtime"
@@ -22,6 +23,8 @@ type RedisSentinelReconciler struct {
2223
Dk8sClient dynamic.Interface
2324
Log logr.Logger
2425
Scheme *runtime.Scheme
26+
27+
ReplicationWatcher *intctrlutil.ResourceWatcher
2528
}
2629

2730
func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
@@ -55,6 +58,17 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques
5558
return intctrlutil.RequeueAfter(reqLogger, time.Second*10, "Redis Replication is specified but not ready")
5659
}
5760

61+
if instance.Spec.RedisSentinelConfig != nil {
62+
r.ReplicationWatcher.Watch(
63+
ctx,
64+
types.NamespacedName{
65+
Namespace: req.Namespace,
66+
Name: instance.Spec.RedisSentinelConfig.RedisReplicationName,
67+
},
68+
req.NamespacedName,
69+
)
70+
}
71+
5872
// Create Redis Sentinel
5973
err = k8sutils.CreateRedisSentinel(ctx, r.K8sClient, r.Log, instance, r.K8sClient, r.Dk8sClient)
6074
if err != nil {
@@ -71,12 +85,13 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques
7185
if err != nil {
7286
return intctrlutil.RequeueWithError(err, reqLogger, "")
7387
}
74-
return intctrlutil.RequeueAfter(reqLogger, time.Second*10, "")
88+
return intctrlutil.Reconciled()
7589
}
7690

7791
// SetupWithManager sets up the controller with the Manager.
7892
func (r *RedisSentinelReconciler) SetupWithManager(mgr ctrl.Manager) error {
7993
return ctrl.NewControllerManagedBy(mgr).
8094
For(&redisv1beta2.RedisSentinel{}).
95+
Watches(&redisv1beta2.RedisReplication{}, r.ReplicationWatcher).
8196
Complete(r)
8297
}

pkg/controllers/redissentinel/redissentinel_controller_suite_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"time"
2424

2525
redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2"
26+
intctrlutil "github.com/OT-CONTAINER-KIT/redis-operator/pkg/controllerutil"
2627
. "github.com/onsi/ginkgo/v2"
2728
. "github.com/onsi/gomega"
2829
"github.com/onsi/gomega/gexec"
@@ -100,10 +101,11 @@ var _ = BeforeSuite(func() {
100101
Expect(err).ToNot(HaveOccurred())
101102

102103
err = (&RedisSentinelReconciler{
103-
Client: k8sManager.GetClient(),
104-
K8sClient: k8sClient,
105-
Dk8sClient: dk8sClient,
106-
Scheme: k8sManager.GetScheme(),
104+
Client: k8sManager.GetClient(),
105+
K8sClient: k8sClient,
106+
Dk8sClient: dk8sClient,
107+
Scheme: k8sManager.GetScheme(),
108+
ReplicationWatcher: intctrlutil.NewResourceWatcher(),
107109
}).SetupWithManager(k8sManager)
108110
Expect(err).ToNot(HaveOccurred())
109111

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package controllerutil
2+
3+
import (
4+
"context"
5+
6+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
7+
"k8s.io/apimachinery/pkg/types"
8+
"k8s.io/client-go/util/workqueue"
9+
"sigs.k8s.io/controller-runtime/pkg/event"
10+
"sigs.k8s.io/controller-runtime/pkg/handler"
11+
"sigs.k8s.io/controller-runtime/pkg/reconcile"
12+
)
13+
14+
// ResourceWatcher implements handler.EventHandler and is used to trigger reconciliation when
15+
// a watched object changes. It's designed to only be used for a single type of object.
16+
// If multiple types should be watched, one ResourceWatcher for each type should be used.
17+
type ResourceWatcher struct {
18+
watched map[types.NamespacedName][]types.NamespacedName
19+
}
20+
21+
var _ handler.EventHandler = &ResourceWatcher{}
22+
23+
// NewResourceWatcher will create a new ResourceWatcher with no watched objects.
24+
func NewResourceWatcher() *ResourceWatcher {
25+
return &ResourceWatcher{
26+
watched: make(map[types.NamespacedName][]types.NamespacedName),
27+
}
28+
}
29+
30+
// Watch will add a new object to watch.
31+
func (w ResourceWatcher) Watch(ctx context.Context, watchedName, dependentName types.NamespacedName) {
32+
existing, hasExisting := w.watched[watchedName]
33+
if !hasExisting {
34+
existing = []types.NamespacedName{}
35+
}
36+
37+
for _, dependent := range existing {
38+
if dependent == dependentName {
39+
return
40+
}
41+
}
42+
w.watched[watchedName] = append(existing, dependentName)
43+
}
44+
45+
func (w ResourceWatcher) Create(ctx context.Context, event event.CreateEvent, queue workqueue.RateLimitingInterface) {
46+
w.handleEvent(event.Object, queue)
47+
}
48+
49+
func (w ResourceWatcher) Update(ctx context.Context, event event.UpdateEvent, queue workqueue.RateLimitingInterface) {
50+
w.handleEvent(event.ObjectOld, queue)
51+
}
52+
53+
func (w ResourceWatcher) Delete(ctx context.Context, event event.DeleteEvent, queue workqueue.RateLimitingInterface) {
54+
w.handleEvent(event.Object, queue)
55+
}
56+
57+
func (w ResourceWatcher) Generic(ctx context.Context, event event.GenericEvent, queue workqueue.RateLimitingInterface) {
58+
w.handleEvent(event.Object, queue)
59+
}
60+
61+
// handleEvent is called when an event is received for an object.
62+
// It will check if the object is being watched and trigger a reconciliation for
63+
// the dependent object.
64+
func (w ResourceWatcher) handleEvent(meta metav1.Object, queue workqueue.RateLimitingInterface) {
65+
changedObjectName := types.NamespacedName{
66+
Name: meta.GetName(),
67+
Namespace: meta.GetNamespace(),
68+
}
69+
70+
// Enqueue reconciliation for each dependent object.
71+
for _, dep := range w.watched[changedObjectName] {
72+
queue.Add(reconcile.Request{
73+
NamespacedName: dep,
74+
})
75+
}
76+
}

tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml renamed to tests/e2e-chainsaw/v1beta2/setup/ha/chainsaw-test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
apiVersion: chainsaw.kyverno.io/v1alpha1
33
kind: Test
44
metadata:
5-
name: ha-failover
5+
name: setup-ha
66
spec:
77
steps:
88
- try:
File renamed without changes.

tests/e2e-chainsaw/v1beta2/setup/ha/replication-password/chainsaw-test.yaml

Lines changed: 0 additions & 53 deletions
This file was deleted.

tests/e2e-chainsaw/v1beta2/setup/ha/replication-password/password.yaml

Lines changed: 0 additions & 8 deletions
This file was deleted.

tests/e2e-chainsaw/v1beta2/setup/ha/replication-password/ready-secret.yaml

Lines changed: 0 additions & 6 deletions
This file was deleted.

0 commit comments

Comments
 (0)