diff --git a/.golangci.yml b/.golangci.yml index 603eccad5..2a38a4fa8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -34,7 +34,7 @@ run: - k8s.io/client-go - github.com/banzaicloud/k8s-objectmatcher - github.com/go-logr/logr - - github.com/go-redis/redis + - github.com/redis/go-redis - github.com/onsi/ginkgo - github.com/onsi/gomega - github.com/pkg/errors diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index d1d9b18a8..98530728d 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -76,19 +76,19 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request // check whether the redis is leader or not ? // if not true then make it leader pod - if !(k8sutils.VerifyLeaderPod(instance)) { + if !(k8sutils.VerifyLeaderPod(ctx, instance)) { // lastLeaderPod is slaving right now Make it the master Pod // We have to bring a manual failover here to make it a leaderPod // clusterFailover should also include the clusterReplicate since we have to map the followers to new leader - k8sutils.ClusterFailover(instance) + k8sutils.ClusterFailover(ctx, instance) } // Step 1 Rehard the Cluster k8sutils.ReshardRedisCluster(instance) // Step 2 Remove the Follower Node - k8sutils.RemoveRedisFollowerNodesFromCluster(instance) + k8sutils.RemoveRedisFollowerNodesFromCluster(ctx, instance) // Step 3 Remove the Leader Node - k8sutils.RemoveRedisNodeFromCluster(instance) + k8sutils.RemoveRedisNodeFromCluster(ctx, instance) // Step 4 Rebalance the cluster k8sutils.RebalanceRedisCluster(instance) return ctrl.Result{RequeueAfter: time.Second * 100}, nil @@ -175,17 +175,17 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } reqLogger.Info("Creating redis cluster by executing cluster creation commands", "Leaders.Ready", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Followers.Ready", strconv.Itoa(int(redisFollowerInfo.Status.ReadyReplicas))) - if k8sutils.CheckRedisNodeCount(instance, "") != totalReplicas { - leaderCount := k8sutils.CheckRedisNodeCount(instance, "leader") + if k8sutils.CheckRedisNodeCount(ctx, instance, "") != totalReplicas { + leaderCount := k8sutils.CheckRedisNodeCount(ctx, instance, "leader") if leaderCount != leaderReplicas { reqLogger.Info("Not all leader are part of the cluster...", "Leaders.Count", leaderCount, "Instance.Size", leaderReplicas) if leaderCount <= 2 { - k8sutils.ExecuteRedisClusterCommand(instance) + k8sutils.ExecuteRedisClusterCommand(ctx, instance) } else { if leaderCount < leaderReplicas { // Scale up the cluster // Step 2 : Add Redis Node - k8sutils.AddRedisNodeToCluster(instance) + k8sutils.AddRedisNodeToCluster(ctx, instance) // Step 3 Rebalance the cluster using the empty masters k8sutils.RebalanceRedisClusterEmptyMasters(instance) } @@ -193,16 +193,16 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } else { if followerReplicas > 0 && redisFollowerInfo.Status.ReadyReplicas == followerReplicas { reqLogger.Info("All leader are part of the cluster, adding follower/replicas", "Leaders.Count", leaderCount, "Instance.Size", leaderReplicas, "Follower.Replicas", followerReplicas) - k8sutils.ExecuteRedisReplicationCommand(instance) + k8sutils.ExecuteRedisReplicationCommand(ctx, instance) } else { reqLogger.Info("no follower/replicas configured, skipping replication configuration", "Leaders.Count", leaderCount, "Leader.Size", leaderReplicas, "Follower.Replicas", followerReplicas) } } } else { reqLogger.Info("Redis leader count is desired") - if int(totalReplicas) > 1 && k8sutils.CheckRedisClusterState(instance) >= int(totalReplicas)-1 { + if int(totalReplicas) > 1 && k8sutils.CheckRedisClusterState(ctx, instance) >= int(totalReplicas)-1 { reqLogger.Info("Redis leader is not desired, executing failover operation") - err = k8sutils.ExecuteFailoverOperation(instance) + err = k8sutils.ExecuteFailoverOperation(ctx, instance) if err != nil { return ctrl.Result{RequeueAfter: time.Second * 10}, err } @@ -211,8 +211,8 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } // Check If there is No Empty Master Node - if k8sutils.CheckRedisNodeCount(instance, "") == totalReplicas { - k8sutils.CheckIfEmptyMasters(instance) + if k8sutils.CheckRedisNodeCount(ctx, instance, "") == totalReplicas { + k8sutils.CheckIfEmptyMasters(ctx, instance) } reqLogger.Info("Will reconcile redis cluster operator in again 10 seconds") diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index 086f5658a..ab7efb08e 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -76,11 +76,11 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req reqLogger.Info("Creating redis replication by executing replication creation commands", "Replication.Ready", strconv.Itoa(int(redisReplicationInfo.Status.ReadyReplicas))) - if len(k8sutils.GetRedisNodesByRole(instance, "master")) > int(leaderReplicas) { + if len(k8sutils.GetRedisNodesByRole(ctx, instance, "master")) > int(leaderReplicas) { - masterNodes := k8sutils.GetRedisNodesByRole(instance, "master") - slaveNodes := k8sutils.GetRedisNodesByRole(instance, "slave") - err := k8sutils.CreateMasterSlaveReplication(instance, masterNodes, slaveNodes) + masterNodes := k8sutils.GetRedisNodesByRole(ctx, instance, "master") + slaveNodes := k8sutils.GetRedisNodesByRole(ctx, instance, "slave") + err := k8sutils.CreateMasterSlaveReplication(ctx, instance, masterNodes, slaveNodes) if err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index 71e8583eb..33170cff1 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -51,7 +51,7 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques } // Create Redis Sentinel - err = k8sutils.CreateRedisSentinel(instance) + err = k8sutils.CreateRedisSentinel(ctx, instance) if err != nil { return ctrl.Result{}, err } diff --git a/go.mod b/go.mod index 161af7150..ed287b58b 100644 --- a/go.mod +++ b/go.mod @@ -5,10 +5,10 @@ go 1.21 require ( github.com/banzaicloud/k8s-objectmatcher v1.7.0 github.com/go-logr/logr v1.2.4 - github.com/go-redis/redis v6.15.9+incompatible github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.27.10 github.com/pkg/errors v0.9.1 + github.com/redis/go-redis/v9 v9.2.1 github.com/stretchr/testify v1.8.4 k8s.io/api v0.28.2 k8s.io/apimachinery v0.28.2 @@ -22,6 +22,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect diff --git a/go.sum b/go.sum index e4c74033a..8eedf22f0 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,10 @@ github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -22,6 +26,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= @@ -57,8 +63,6 @@ github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nA github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= -github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= @@ -177,6 +181,8 @@ github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdO github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= +github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= diff --git a/k8sutils/cluster-scaling.go b/k8sutils/cluster-scaling.go index f15867ac0..f58279834 100644 --- a/k8sutils/cluster-scaling.go +++ b/k8sutils/cluster-scaling.go @@ -1,18 +1,20 @@ package k8sutils import ( + "context" "strconv" "strings" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" - "github.com/go-redis/redis" + redis "github.com/redis/go-redis/v9" ) // Reshard the redis Cluster func ReshardRedisCluster(cr *redisv1beta2.RedisCluster) { + ctx := context.TODO() logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) var cmd []string - currentRedisCount := CheckRedisNodeCount(cr, "leader") + currentRedisCount := CheckRedisNodeCount(ctx, cr, "leader") // Transfer Pod details transferPOD := RedisDetails{ @@ -46,17 +48,17 @@ func ReshardRedisCluster(cr *redisv1beta2.RedisCluster) { //--cluster-from --cluster-to --cluster-slots --cluster-yes // Remove Node - removeNodeID := getRedisNodeID(cr, removePOD) + removeNodeID := getRedisNodeID(ctx, cr, removePOD) cmd = append(cmd, "--cluster-from") cmd = append(cmd, removeNodeID) // Transfer Node - transferNodeID := getRedisNodeID(cr, transferPOD) + transferNodeID := getRedisNodeID(ctx, cr, transferPOD) cmd = append(cmd, "--cluster-to") cmd = append(cmd, transferNodeID) // Cluster Slots - slot := getRedisClusterSlots(cr, removeNodeID) + slot := getRedisClusterSlots(ctx, cr, removeNodeID) cmd = append(cmd, "--cluster-slots") cmd = append(cmd, slot) @@ -71,13 +73,13 @@ func ReshardRedisCluster(cr *redisv1beta2.RedisCluster) { executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") } -func getRedisClusterSlots(cr *redisv1beta2.RedisCluster, nodeID string) string { +func getRedisClusterSlots(ctx context.Context, cr *redisv1beta2.RedisCluster, nodeID string) string { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) totalSlots := 0 redisClient := configureRedisClient(cr, cr.ObjectMeta.Name+"-leader-0") defer redisClient.Close() - redisClusterInfo, err := redisClient.ClusterNodes().Result() + redisClusterInfo, err := redisClient.ClusterNodes(ctx).Result() if err != nil { logger.Error(err, "Failed to Get Cluster Info") return "" @@ -112,20 +114,20 @@ func getRedisClusterSlots(cr *redisv1beta2.RedisCluster, nodeID string) string { } // getRedisNodeID would return nodeID of a redis node by passing pod -func getRedisNodeID(cr *redisv1beta2.RedisCluster, pod RedisDetails) string { +func getRedisNodeID(ctx context.Context, cr *redisv1beta2.RedisCluster, pod RedisDetails) string { var client *redis.Client logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) client = configureRedisClient(cr, pod.PodName) defer client.Close() - pong, err := client.Ping().Result() + pong, err := client.Ping(ctx).Result() if err != nil || pong != "PONG" { logger.Error(err, "Failed to ping Redis server") return "" } - cmd := redis.NewStringCmd("cluster", "myid") - err = client.Process(cmd) + cmd := redis.NewStringCmd(ctx, "cluster", "myid") + err = client.Process(ctx, cmd) if err != nil { logger.Error(err, "Redis command failed with this error") return "" @@ -174,17 +176,17 @@ func RebalanceRedisClusterEmptyMasters(cr *redisv1beta2.RedisCluster) { executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-1") } -func CheckIfEmptyMasters(cr *redisv1beta2.RedisCluster) { +func CheckIfEmptyMasters(ctx context.Context, cr *redisv1beta2.RedisCluster) { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - totalRedisLeaderNodes := CheckRedisNodeCount(cr, "leader") + totalRedisLeaderNodes := CheckRedisNodeCount(ctx, cr, "leader") for i := 0; i < int(totalRedisLeaderNodes); i++ { pod := RedisDetails{ PodName: cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(i), Namespace: cr.Namespace, } - podNodeID := getRedisNodeID(cr, pod) - podSlots := getRedisClusterSlots(cr, podNodeID) + podNodeID := getRedisNodeID(ctx, cr, pod) + podSlots := getRedisClusterSlots(ctx, cr, podNodeID) if podSlots == "0" || podSlots == "" { logger.V(1).Info("Found Empty Redis Leader Node", "pod", pod) @@ -227,10 +229,10 @@ func RebalanceRedisCluster(cr *redisv1beta2.RedisCluster) { } // Add redis cluster node would add a node to the existing redis cluster using redis-cli -func AddRedisNodeToCluster(cr *redisv1beta2.RedisCluster) { +func AddRedisNodeToCluster(ctx context.Context, cr *redisv1beta2.RedisCluster) { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) var cmd []string - activeRedisNode := CheckRedisNodeCount(cr, "leader") + activeRedisNode := CheckRedisNodeCount(ctx, cr, "leader") newPod := RedisDetails{ PodName: cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(int(activeRedisNode)), @@ -267,12 +269,12 @@ func AddRedisNodeToCluster(cr *redisv1beta2.RedisCluster) { } // getAttachedFollowerNodeIDs would return a slice of redis followers attached to a redis leader -func getAttachedFollowerNodeIDs(cr *redisv1beta2.RedisCluster, masterNodeID string) []string { +func getAttachedFollowerNodeIDs(ctx context.Context, cr *redisv1beta2.RedisCluster, masterNodeID string) []string { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) redisClient := configureRedisClient(cr, cr.ObjectMeta.Name+"-leader-0") defer redisClient.Close() - redisClusterInfo, err := redisClient.ClusterNodes().Result() + redisClusterInfo, err := redisClient.ClusterNodes(ctx).Result() if err != nil { logger.Error(err, "Failed to Get Cluster Info") return nil @@ -297,10 +299,10 @@ func getAttachedFollowerNodeIDs(cr *redisv1beta2.RedisCluster, masterNodeID stri } // Remove redis follower node would remove all follower nodes of last leader node using redis-cli -func RemoveRedisFollowerNodesFromCluster(cr *redisv1beta2.RedisCluster) { +func RemoveRedisFollowerNodesFromCluster(ctx context.Context, cr *redisv1beta2.RedisCluster) { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) var cmd []string - currentRedisCount := CheckRedisNodeCount(cr, "leader") + currentRedisCount := CheckRedisNodeCount(ctx, cr, "leader") existingPod := RedisDetails{ PodName: cr.ObjectMeta.Name + "-leader-0", @@ -323,8 +325,8 @@ func RemoveRedisFollowerNodesFromCluster(cr *redisv1beta2.RedisCluster) { } cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) - lastLeaderPodNodeID := getRedisNodeID(cr, lastLeaderPod) - followerNodeIDs := getAttachedFollowerNodeIDs(cr, lastLeaderPodNodeID) + lastLeaderPodNodeID := getRedisNodeID(ctx, cr, lastLeaderPod) + followerNodeIDs := getAttachedFollowerNodeIDs(ctx, cr, lastLeaderPodNodeID) cmd = append(cmd, "--cluster", "del-node") if *cr.Spec.ClusterVersion == "v7" { @@ -343,10 +345,10 @@ func RemoveRedisFollowerNodesFromCluster(cr *redisv1beta2.RedisCluster) { } // Remove redis cluster node would remove last node to the existing redis cluster using redis-cli -func RemoveRedisNodeFromCluster(cr *redisv1beta2.RedisCluster) { +func RemoveRedisNodeFromCluster(ctx context.Context, cr *redisv1beta2.RedisCluster) { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) var cmd []string - currentRedisCount := CheckRedisNodeCount(cr, "leader") + currentRedisCount := CheckRedisNodeCount(ctx, cr, "leader") existingPod := RedisDetails{ PodName: cr.ObjectMeta.Name + "-leader-0", @@ -365,7 +367,7 @@ func RemoveRedisNodeFromCluster(cr *redisv1beta2.RedisCluster) { cmd = append(cmd, getRedisServerIP(existingPod)+":6379") } - removePodNodeID := getRedisNodeID(cr, removePod) + removePodNodeID := getRedisNodeID(ctx, cr, removePod) cmd = append(cmd, removePodNodeID) if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -380,20 +382,20 @@ func RemoveRedisNodeFromCluster(cr *redisv1beta2.RedisCluster) { cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) logger.V(1).Info("Redis cluster leader remove command is", "Command", cmd) - if getRedisClusterSlots(cr, removePodNodeID) != "0" { + if getRedisClusterSlots(ctx, cr, removePodNodeID) != "0" { logger.V(1).Info("Skipping execution remove leader not empty", "cmd", cmd) } executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") } // verifyLeaderPod return true if the pod is leader/master -func VerifyLeaderPod(cr *redisv1beta2.RedisCluster) bool { +func VerifyLeaderPod(ctx context.Context, cr *redisv1beta2.RedisCluster) bool { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - podName := cr.Name + "-leader-" + strconv.Itoa(int(CheckRedisNodeCount(cr, "leader"))-1) + podName := cr.Name + "-leader-" + strconv.Itoa(int(CheckRedisNodeCount(ctx, cr, "leader"))-1) redisClient := configureRedisClient(cr, podName) defer redisClient.Close() - info, err := redisClient.Info("replication").Result() + info, err := redisClient.Info(ctx, "replication").Result() if err != nil { logger.Error(err, "Failed to Get the role Info of the", "redis pod", podName) return false @@ -410,9 +412,9 @@ func VerifyLeaderPod(cr *redisv1beta2.RedisCluster) bool { return false } -func ClusterFailover(cr *redisv1beta2.RedisCluster) { +func ClusterFailover(ctx context.Context, cr *redisv1beta2.RedisCluster) { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - slavePodName := cr.Name + "-leader-" + strconv.Itoa(int(CheckRedisNodeCount(cr, "leader"))-1) + slavePodName := cr.Name + "-leader-" + strconv.Itoa(int(CheckRedisNodeCount(ctx, cr, "leader"))-1) // cmd = redis-cli cluster failover -a var cmd []string diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 781d4f371..fe11fd24c 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -32,7 +32,7 @@ type RedisReplicationObject struct { } // Redis Sentinel Create the Redis Sentinel Setup -func CreateRedisSentinel(cr *redisv1beta2.RedisSentinel) error { +func CreateRedisSentinel(ctx context.Context, cr *redisv1beta2.RedisSentinel) error { prop := RedisSentinelSTS{ RedisStateFulType: "sentinel", Affinity: cr.Spec.Affinity, @@ -45,7 +45,7 @@ func CreateRedisSentinel(cr *redisv1beta2.RedisSentinel) error { prop.ExternalConfig = cr.Spec.RedisSentinelConfig.AdditionalSentinelConfig } - return prop.CreateRedisSentinelSetup(cr) + return prop.CreateRedisSentinelSetup(ctx, cr) } @@ -59,7 +59,7 @@ func CreateRedisSentinelService(cr *redisv1beta2.RedisSentinel) error { } // Create Redis Sentinel Cluster Setup -func (service RedisSentinelSTS) CreateRedisSentinelSetup(cr *redisv1beta2.RedisSentinel) error { +func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, cr *redisv1beta2.RedisSentinel) error { stateFulName := cr.ObjectMeta.Name + "-" + service.RedisStateFulType logger := statefulSetLogger(cr.Namespace, stateFulName) @@ -72,7 +72,7 @@ func (service RedisSentinelSTS) CreateRedisSentinelSetup(cr *redisv1beta2.RedisS generateRedisSentinelParams(cr, service.getSentinelCount(cr), service.ExternalConfig, service.Affinity), redisSentinelAsOwner(cr), generateRedisSentinelInitContainerParams(cr), - generateRedisSentinelContainerParams(cr, service.ReadinessProbe, service.LivenessProbe), + generateRedisSentinelContainerParams(ctx, cr, service.ReadinessProbe, service.LivenessProbe), cr.Spec.Sidecars, ) @@ -141,7 +141,7 @@ func generateRedisSentinelInitContainerParams(cr *redisv1beta2.RedisSentinel) in } // Create Redis Sentinel Statefulset Container Params -func generateRedisSentinelContainerParams(cr *redisv1beta2.RedisSentinel, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe) containerParameters { +func generateRedisSentinelContainerParams(ctx context.Context, cr *redisv1beta2.RedisSentinel, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe) containerParameters { trueProperty := true falseProperty := false @@ -151,7 +151,7 @@ func generateRedisSentinelContainerParams(cr *redisv1beta2.RedisSentinel, readin ImagePullPolicy: cr.Spec.KubernetesConfig.ImagePullPolicy, Resources: cr.Spec.KubernetesConfig.Resources, SecurityContext: cr.Spec.SecurityContext, - AdditionalEnvVariable: getSentinelEnvVariable(cr), + AdditionalEnvVariable: getSentinelEnvVariable(ctx, cr), } if cr.Spec.EnvVars != nil { containerProp.EnvVars = cr.Spec.EnvVars @@ -240,7 +240,7 @@ func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2. } -func getSentinelEnvVariable(cr *redisv1beta2.RedisSentinel) *[]corev1.EnvVar { +func getSentinelEnvVariable(ctx context.Context, cr *redisv1beta2.RedisSentinel) *[]corev1.EnvVar { if cr.Spec.RedisSentinelConfig == nil { return &[]corev1.EnvVar{} @@ -253,7 +253,7 @@ func getSentinelEnvVariable(cr *redisv1beta2.RedisSentinel) *[]corev1.EnvVar { }, { Name: "IP", - Value: getRedisReplicationMasterIP(cr), + Value: getRedisReplicationMasterIP(ctx, cr), }, { Name: "PORT", @@ -281,7 +281,7 @@ func getSentinelEnvVariable(cr *redisv1beta2.RedisSentinel) *[]corev1.EnvVar { } -func getRedisReplicationMasterIP(cr *redisv1beta2.RedisSentinel) string { +func getRedisReplicationMasterIP(ctx context.Context, cr *redisv1beta2.RedisSentinel) string { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) replicationName := cr.Spec.RedisSentinelConfig.RedisReplicationName @@ -317,7 +317,7 @@ func getRedisReplicationMasterIP(cr *redisv1beta2.RedisSentinel) string { return "" } - masterPods := GetRedisNodesByRole(&replicationInstance, "master") + masterPods := GetRedisNodesByRole(ctx, &replicationInstance, "master") if len(masterPods) == 0 { realMasterPod = "" @@ -326,7 +326,7 @@ func getRedisReplicationMasterIP(cr *redisv1beta2.RedisSentinel) string { } else if len(masterPods) == 1 { realMasterPod = masterPods[0] } else { - realMasterPod = checkAttachedSlave(&replicationInstance, masterPods) + realMasterPod = checkAttachedSlave(ctx, &replicationInstance, masterPods) } realMasterInfo := RedisDetails{ diff --git a/k8sutils/redis.go b/k8sutils/redis.go index f7bbcb576..6973363f0 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -11,7 +11,7 @@ import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/go-logr/logr" - "github.com/go-redis/redis" + redis "github.com/redis/go-redis/v9" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes/scheme" @@ -87,13 +87,13 @@ func CreateMultipleLeaderRedisCommand(cr *redisv1beta2.RedisCluster) []string { } // ExecuteRedisClusterCommand will execute redis cluster creation command -func ExecuteRedisClusterCommand(cr *redisv1beta2.RedisCluster) { +func ExecuteRedisClusterCommand(ctx context.Context, cr *redisv1beta2.RedisCluster) { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) var cmd []string replicas := cr.Spec.GetReplicaCounts("leader") switch int(replicas) { case 1: - err := executeFailoverCommand(cr, "leader") + err := executeFailoverCommand(ctx, cr, "leader") if err != nil { logger.Error(err, "error executing failover command") } @@ -154,14 +154,14 @@ func createRedisReplicationCommand(cr *redisv1beta2.RedisCluster, leaderPod Redi } // ExecuteRedisReplicationCommand will execute the replication command -func ExecuteRedisReplicationCommand(cr *redisv1beta2.RedisCluster) { +func ExecuteRedisReplicationCommand(ctx context.Context, cr *redisv1beta2.RedisCluster) { var podIP string logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) followerCounts := cr.Spec.GetReplicaCounts("follower") leaderCounts := cr.Spec.GetReplicaCounts("leader") followerPerLeader := followerCounts / leaderCounts - nodes := checkRedisCluster(cr) + nodes := checkRedisCluster(ctx, cr) for followerIdx := 0; followerIdx <= int(followerCounts)-1; { for i := 0; i < int(followerPerLeader) && followerIdx <= int(followerCounts)-1; i++ { followerPod := RedisDetails{ @@ -177,7 +177,7 @@ func ExecuteRedisReplicationCommand(cr *redisv1beta2.RedisCluster) { logger.V(1).Info("Adding node to cluster.", "Node.IP", podIP, "Follower.Pod", followerPod) cmd := createRedisReplicationCommand(cr, leaderPod, followerPod) redisClient := configureRedisClient(cr, followerPod.PodName) - pong, err := redisClient.Ping().Result() + pong, err := redisClient.Ping(ctx).Result() redisClient.Close() if err != nil { logger.Error(err, "Failed to ping Redis server", "Follower.Pod", followerPod) @@ -198,13 +198,13 @@ func ExecuteRedisReplicationCommand(cr *redisv1beta2.RedisCluster) { } // checkRedisCluster will check the redis cluster have sufficient nodes or not -func checkRedisCluster(cr *redisv1beta2.RedisCluster) [][]string { +func checkRedisCluster(ctx context.Context, cr *redisv1beta2.RedisCluster) [][]string { var client *redis.Client logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) client = configureRedisClient(cr, cr.ObjectMeta.Name+"-leader-0") defer client.Close() - cmd := redis.NewStringCmd("cluster", "nodes") - err := client.Process(cmd) + cmd := redis.NewStringCmd(ctx, "cluster", "nodes") + err := client.Process(ctx, cmd) if err != nil { logger.Error(err, "Redis command failed with this error") } @@ -226,14 +226,14 @@ func checkRedisCluster(cr *redisv1beta2.RedisCluster) [][]string { } // ExecuteFailoverOperation will execute redis failover operations -func ExecuteFailoverOperation(cr *redisv1beta2.RedisCluster) error { +func ExecuteFailoverOperation(ctx context.Context, cr *redisv1beta2.RedisCluster) error { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - err := executeFailoverCommand(cr, "leader") + err := executeFailoverCommand(ctx, cr, "leader") if err != nil { logger.Error(err, "Redis command failed for leader nodes") return err } - err = executeFailoverCommand(cr, "follower") + err = executeFailoverCommand(ctx, cr, "follower") if err != nil { logger.Error(err, "Redis command failed for follower nodes") return err @@ -242,7 +242,7 @@ func ExecuteFailoverOperation(cr *redisv1beta2.RedisCluster) error { } // executeFailoverCommand will execute failover command -func executeFailoverCommand(cr *redisv1beta2.RedisCluster, role string) error { +func executeFailoverCommand(ctx context.Context, cr *redisv1beta2.RedisCluster, role string) error { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) replicas := cr.Spec.GetReplicaCounts(role) podName := fmt.Sprintf("%s-%s-", cr.ObjectMeta.Name, role) @@ -250,18 +250,18 @@ func executeFailoverCommand(cr *redisv1beta2.RedisCluster, role string) error { logger.V(1).Info("Executing redis failover operations", "Redis Node", podName+strconv.Itoa(podCount)) client := configureRedisClient(cr, podName+strconv.Itoa(podCount)) defer client.Close() - cmd := redis.NewStringCmd("cluster", "reset") - err := client.Process(cmd) + cmd := redis.NewStringCmd(ctx, "cluster", "reset") + err := client.Process(ctx, cmd) if err != nil { logger.Error(err, "Redis command failed with this error") - flushcommand := redis.NewStringCmd("flushall") - err = client.Process(flushcommand) + flushcommand := redis.NewStringCmd(ctx, "flushall") + err = client.Process(ctx, flushcommand) if err != nil { logger.Error(err, "Redis flush command failed with this error") return err } } - err = client.Process(cmd) + err = client.Process(ctx, cmd) if err != nil { logger.Error(err, "Redis command failed with this error") return err @@ -277,10 +277,10 @@ func executeFailoverCommand(cr *redisv1beta2.RedisCluster, role string) error { } // CheckRedisNodeCount will check the count of redis nodes -func CheckRedisNodeCount(cr *redisv1beta2.RedisCluster, nodeType string) int32 { +func CheckRedisNodeCount(ctx context.Context, cr *redisv1beta2.RedisCluster, nodeType string) int32 { var redisNodeType string logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - clusterNodes := checkRedisCluster(cr) + clusterNodes := checkRedisCluster(ctx, cr) count := len(clusterNodes) switch nodeType { @@ -306,9 +306,9 @@ func CheckRedisNodeCount(cr *redisv1beta2.RedisCluster, nodeType string) int32 { } // CheckRedisClusterState will check the redis cluster state -func CheckRedisClusterState(cr *redisv1beta2.RedisCluster) int { +func CheckRedisClusterState(ctx context.Context, cr *redisv1beta2.RedisCluster) int { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - clusterNodes := checkRedisCluster(cr) + clusterNodes := checkRedisCluster(ctx, cr) count := 0 for _, node := range clusterNodes { @@ -464,7 +464,7 @@ func configureRedisReplicationClient(cr *redisv1beta2.RedisReplication, podName } // Get Redis nodes by it's role i.e. master, slave and sentinel -func GetRedisNodesByRole(cr *redisv1beta2.RedisReplication, redisRole string) []string { +func GetRedisNodesByRole(ctx context.Context, cr *redisv1beta2.RedisReplication, redisRole string) []string { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) statefulset, err := GetStatefulSet(cr.Namespace, cr.Name) if err != nil { @@ -477,7 +477,7 @@ func GetRedisNodesByRole(cr *redisv1beta2.RedisReplication, redisRole string) [] for i := 0; i < int(replicas); i++ { podName := statefulset.Name + "-" + strconv.Itoa(i) - podRole := checkRedisServerRole(cr, podName) + podRole := checkRedisServerRole(ctx, cr, podName) if podRole == redisRole { pods = append(pods, podName) } @@ -487,12 +487,12 @@ func GetRedisNodesByRole(cr *redisv1beta2.RedisReplication, redisRole string) [] } // Check the Redis Server Role i.e. master, slave and sentinel -func checkRedisServerRole(cr *redisv1beta2.RedisReplication, podName string) string { +func checkRedisServerRole(ctx context.Context, cr *redisv1beta2.RedisReplication, podName string) string { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) redisClient := configureRedisReplicationClient(cr, podName) defer redisClient.Close() - info, err := redisClient.Info("replication").Result() + info, err := redisClient.Info(ctx, "replication").Result() if err != nil { logger.Error(err, "Failed to Get the role Info of the", "redis pod", podName) } @@ -510,7 +510,7 @@ func checkRedisServerRole(cr *redisv1beta2.RedisReplication, podName string) str } // checkAttachedSlave would return redis pod name which has slave -func checkAttachedSlave(cr *redisv1beta2.RedisReplication, masterPods []string) string { +func checkAttachedSlave(ctx context.Context, cr *redisv1beta2.RedisReplication, masterPods []string) string { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) for _, podName := range masterPods { @@ -518,7 +518,7 @@ func checkAttachedSlave(cr *redisv1beta2.RedisReplication, masterPods []string) connected_slaves := "" redisClient := configureRedisReplicationClient(cr, podName) defer redisClient.Close() - info, err := redisClient.Info("replication").Result() + info, err := redisClient.Info(ctx, "replication").Result() if err != nil { logger.Error(err, "Failed to Get the connected slaves Info of the", "redis pod", podName) } @@ -543,11 +543,11 @@ func checkAttachedSlave(cr *redisv1beta2.RedisReplication, masterPods []string) } -func CreateMasterSlaveReplication(cr *redisv1beta2.RedisReplication, masterPods []string, slavePods []string) error { +func CreateMasterSlaveReplication(ctx context.Context, cr *redisv1beta2.RedisReplication, masterPods []string, slavePods []string) error { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) var realMasterPod string - realMasterPod = checkAttachedSlave(cr, masterPods) + realMasterPod = checkAttachedSlave(ctx, cr, masterPods) if len(slavePods) < 1 { realMasterPod = masterPods[0] @@ -568,7 +568,7 @@ func CreateMasterSlaveReplication(cr *redisv1beta2.RedisReplication, masterPods redisClient := configureRedisReplicationClient(cr, masterPods[i]) defer redisClient.Close() logger.V(1).Info("Setting the", "pod", masterPods[i], "to slave of", realMasterPod) - err := redisClient.SlaveOf(realMasterPodIP, "6379").Err() + err := redisClient.SlaveOf(ctx, realMasterPodIP, "6379").Err() if err != nil { logger.Error(err, "Failed to set", "pod", masterPods[i], "to slave of", realMasterPod) return err