From 7e693f05926438910542e745915b51e575980394 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Sat, 11 Nov 2023 05:59:23 +0530 Subject: [PATCH 1/7] Add test Signed-off-by: Shubham Gupta --- k8sutils/cluster-scaling.go | 16 ++-- k8sutils/redis-sentinel.go | 2 +- k8sutils/redis.go | 79 ++++++++++--------- k8sutils/redis_test.go | 150 ++++++++++++++++++++++++++++++++++++ 4 files changed, 200 insertions(+), 47 deletions(-) diff --git a/k8sutils/cluster-scaling.go b/k8sutils/cluster-scaling.go index 8304d0060..bd7d101a2 100644 --- a/k8sutils/cluster-scaling.go +++ b/k8sutils/cluster-scaling.go @@ -32,7 +32,7 @@ func ReshardRedisCluster(client kubernetes.Interface, logger logr.Logger, cr *re if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(transferPOD, cr, "leader")+":6379") } else { - cmd = append(cmd, getRedisServerIP(transferPOD)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, transferPOD)+":6379") } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -153,7 +153,7 @@ func RebalanceRedisClusterEmptyMasters(client kubernetes.Interface, logger logr. if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(pod, cr, "leader")+":6379") } else { - cmd = append(cmd, getRedisServerIP(pod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, pod)+":6379") } cmd = append(cmd, "--cluster-use-empty-masters") @@ -205,7 +205,7 @@ func RebalanceRedisCluster(client kubernetes.Interface, logger logr.Logger, cr * if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(pod, cr, "leader")+":6379") } else { - cmd = append(cmd, getRedisServerIP(pod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, pod)+":6379") } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -243,8 +243,8 @@ func AddRedisNodeToCluster(ctx context.Context, client kubernetes.Interface, log cmd = append(cmd, getRedisHostname(newPod, cr, "leader")+":6379") cmd = append(cmd, getRedisHostname(existingPod, cr, "leader")+":6379") } else { - cmd = append(cmd, getRedisServerIP(newPod)+":6379") - cmd = append(cmd, getRedisServerIP(existingPod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, newPod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, existingPod)+":6379") } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -323,7 +323,7 @@ func RemoveRedisFollowerNodesFromCluster(ctx context.Context, client kubernetes. if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(existingPod, cr, "leader")+":6379") } else { - cmd = append(cmd, getRedisServerIP(existingPod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, existingPod)+":6379") } for _, followerNodeID := range followerNodeIDs { @@ -354,7 +354,7 @@ func RemoveRedisNodeFromCluster(ctx context.Context, client kubernetes.Interface if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(existingPod, cr, "leader")+":6379") } else { - cmd = append(cmd, getRedisServerIP(existingPod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, existingPod)+":6379") } removePodNodeID := getRedisNodeID(ctx, client, logger, cr, removePod) @@ -415,7 +415,7 @@ func ClusterFailover(ctx context.Context, client kubernetes.Interface, logger lo if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(pod, cr, "leader")+":6379") } else { - cmd = append(cmd, getRedisServerIP(pod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, pod)+":6379") } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 42e96b38b..9977fa644 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -336,6 +336,6 @@ func getRedisReplicationMasterIP(ctx context.Context, client kubernetes.Interfac Namespace: replicationNamespace, } - realMasterPodIP := getRedisServerIP(realMasterInfo) + realMasterPodIP := getRedisServerIP(client, logger, realMasterInfo) return realMasterPodIP } diff --git a/k8sutils/redis.go b/k8sutils/redis.go index a34a7934a..432681e10 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -26,28 +26,31 @@ type RedisDetails struct { } // getRedisServerIP will return the IP of redis service -func getRedisServerIP(redisInfo RedisDetails) string { - logger := generateRedisManagerLogger(redisInfo.Namespace, redisInfo.PodName) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Error in getting k8s client") - return "" - } +func getRedisServerIP(client kubernetes.Interface, logger logr.Logger, redisInfo RedisDetails) string { + logger.V(1).Info("Fetching Redis pod", "namespace", redisInfo.Namespace, "podName", redisInfo.PodName) + redisPod, err := client.CoreV1().Pods(redisInfo.Namespace).Get(context.TODO(), redisInfo.PodName, metav1.GetOptions{}) if err != nil { - logger.Error(err, "Error in getting redis pod IP") + logger.Error(err, "Error in getting Redis pod IP", "namespace", redisInfo.Namespace, "podName", redisInfo.PodName) + return "" } redisIP := redisPod.Status.PodIP - // If we're NOT IPv4, assume were IPv6.. - if redisIP != "" { - if net.ParseIP(redisIP).To4() == nil { - logger.V(1).Info("Redis is IPv6", "ip", redisIP, "ipv6", net.ParseIP(redisIP).To16()) - redisIP = fmt.Sprintf("[%s]", redisIP) - } + logger.V(1).Info("Fetched Redis pod IP", "ip", redisIP) + + // Check if IP is empty + if redisIP == "" { + logger.V(1).Info("Redis pod IP is empty", "namespace", redisInfo.Namespace, "podName", redisInfo.PodName) + return "" + } + + // If we're NOT IPv4, assume we're IPv6.. + if net.ParseIP(redisIP).To4() == nil { + logger.V(1).Info("Redis is using IPv6", "ip", redisIP) + redisIP = fmt.Sprintf("[%s]", redisIP) } - logger.V(1).Info("Successfully got the ip for redis", "ip", redisIP) + logger.V(1).Info("Successfully got the IP for Redis", "ip", redisIP) return redisIP } @@ -58,37 +61,37 @@ func getRedisHostname(redisInfo RedisDetails, cr *redisv1beta2.RedisCluster, rol } // CreateSingleLeaderRedisCommand will create command for single leader cluster creation -func CreateSingleLeaderRedisCommand(cr *redisv1beta2.RedisCluster) []string { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func CreateSingleLeaderRedisCommand(logger logr.Logger, cr *redisv1beta2.RedisCluster) []string { cmd := []string{"redis-cli", "CLUSTER", "ADDSLOTS"} for i := 0; i < 16384; i++ { cmd = append(cmd, strconv.Itoa(i)) } + logger.V(1).Info("Generating Redis Add Slots command for single node cluster", + "BaseCommand", cmd[:3], + "SlotsRange", "0-16383", + "TotalSlots", 16384) - logger.V(1).Info("Redis Add Slots command for single node cluster is", "Command", cmd) return cmd } // CreateMultipleLeaderRedisCommand will create command for single leader cluster creation -func CreateMultipleLeaderRedisCommand(cr *redisv1beta2.RedisCluster) []string { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func CreateMultipleLeaderRedisCommand(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) []string { cmd := []string{"redis-cli", "--cluster", "create"} replicas := cr.Spec.GetReplicaCounts("leader") - for podCount := 0; podCount <= int(replicas)-1; podCount++ { - pod := RedisDetails{ - PodName: cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(podCount), - Namespace: cr.Namespace, - } + for podCount := 0; podCount < int(replicas); podCount++ { + podName := cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(podCount) + var address string if *cr.Spec.ClusterVersion == "v7" { - cmd = append(cmd, getRedisHostname(pod, cr, "leader")+":6379") + address = getRedisHostname(RedisDetails{PodName: podName, Namespace: cr.Namespace}, cr, "leader") + ":6379" } else { - cmd = append(cmd, getRedisServerIP(pod)+":6379") + address = getRedisServerIP(client, logger, RedisDetails{PodName: podName, Namespace: cr.Namespace}) + ":6379" } + cmd = append(cmd, address) } cmd = append(cmd, "--cluster-yes") - logger.V(1).Info("Redis Add Slots command for single node cluster is", "Command", cmd) + logger.V(1).Info("Redis cluster creation command", "CommandBase", cmd[:3], "ClusterVersion", *cr.Spec.ClusterVersion, "Replicas", replicas) return cmd } @@ -102,9 +105,9 @@ func ExecuteRedisClusterCommand(ctx context.Context, client kubernetes.Interface if err != nil { logger.Error(err, "error executing failover command") } - cmd = CreateSingleLeaderRedisCommand(cr) + cmd = CreateSingleLeaderRedisCommand(logger, cr) default: - cmd = CreateMultipleLeaderRedisCommand(cr) + cmd = CreateMultipleLeaderRedisCommand(client, logger, cr) } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -139,8 +142,8 @@ func createRedisReplicationCommand(client kubernetes.Interface, logger logr.Logg cmd = append(cmd, getRedisHostname(followerPod, cr, "follower")+":6379") cmd = append(cmd, getRedisHostname(leaderPod, cr, "leader")+":6379") } else { - cmd = append(cmd, getRedisServerIP(followerPod)+":6379") - cmd = append(cmd, getRedisServerIP(leaderPod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, followerPod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, leaderPod)+":6379") } cmd = append(cmd, "--cluster-slave") @@ -175,7 +178,7 @@ func ExecuteRedisReplicationCommand(ctx context.Context, client kubernetes.Inter PodName: cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(int(followerIdx)%int(leaderCounts)), Namespace: cr.Namespace, } - podIP = getRedisServerIP(followerPod) + podIP = getRedisServerIP(client, logger, followerPod) if !checkRedisNodePresence(cr, nodes, podIP) { logger.V(1).Info("Adding node to cluster.", "Node.IP", podIP, "Follower.Pod", followerPod) cmd := createRedisReplicationCommand(client, logger, cr, leaderPod, followerPod) @@ -330,14 +333,14 @@ func configureRedisClient(client kubernetes.Interface, logger logr.Logger, cr *r logger.Error(err, "Error in getting redis password") } redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerIP(redisInfo) + ":6379", + Addr: getRedisServerIP(client, logger, redisInfo) + ":6379", Password: pass, DB: 0, TLSConfig: getRedisTLSConfig(client, logger, cr, redisInfo), }) } else { redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerIP(redisInfo) + ":6379", + Addr: getRedisServerIP(client, logger, redisInfo) + ":6379", Password: "", DB: 0, TLSConfig: getRedisTLSConfig(client, logger, cr, redisInfo), @@ -451,14 +454,14 @@ func configureRedisReplicationClient(client kubernetes.Interface, logger logr.Lo logger.Error(err, "Error in getting redis password") } redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerIP(redisInfo) + ":6379", + Addr: getRedisServerIP(client, logger, redisInfo) + ":6379", Password: pass, DB: 0, TLSConfig: getRedisReplicationTLSConfig(client, logger, cr, redisInfo), }) } else { redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerIP(redisInfo) + ":6379", + Addr: getRedisServerIP(client, logger, redisInfo) + ":6379", Password: "", DB: 0, TLSConfig: getRedisReplicationTLSConfig(client, logger, cr, redisInfo), @@ -556,7 +559,7 @@ func CreateMasterSlaveReplication(ctx context.Context, client kubernetes.Interfa Namespace: cr.Namespace, } - realMasterPodIP := getRedisServerIP(realMasterInfo) + realMasterPodIP := getRedisServerIP(client, logger, realMasterInfo) for i := 0; i < len(masterPods); i++ { if masterPods[i] != realMasterPod { diff --git a/k8sutils/redis_test.go b/k8sutils/redis_test.go index 3028796dd..3975e43b2 100644 --- a/k8sutils/redis_test.go +++ b/k8sutils/redis_test.go @@ -8,6 +8,11 @@ import ( "testing" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/go-logr/logr/testr" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8sClientFake "k8s.io/client-go/kubernetes/fake" ) func TestCheckRedisNodePresence(t *testing.T) { @@ -38,3 +43,148 @@ func TestCheckRedisNodePresence(t *testing.T) { }) } } + +func TestGetRedisServerIP(t *testing.T) { + tests := []struct { + name string + setup func() *k8sClientFake.Clientset + redisInfo RedisDetails + expectedIP string + expectEmpty bool + }{ + { + name: "Successfully retrieve IPv4 address", + setup: func() *k8sClientFake.Clientset { + return k8sClientFake.NewSimpleClientset(&corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-pod", + Namespace: "default", + }, + Status: corev1.PodStatus{ + PodIP: "192.168.1.1", + }, + }) + }, + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + expectedIP: "192.168.1.1", + expectEmpty: false, + }, + { + name: "Successfully retrieve IPv6 address", + setup: func() *k8sClientFake.Clientset { + return k8sClientFake.NewSimpleClientset(&corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-pod", + Namespace: "default", + }, + Status: corev1.PodStatus{ + PodIP: "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + }, + }) + }, + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + expectedIP: "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]", + expectEmpty: false, + }, + { + name: "Error retrieving pod results in empty IP", + setup: func() *k8sClientFake.Clientset { + client := k8sClientFake.NewSimpleClientset() + return client + }, + redisInfo: RedisDetails{ + PodName: "nonexistent-pod", + Namespace: "default", + }, + expectEmpty: true, + }, + { + name: "Empty results in empty IP", + setup: func() *k8sClientFake.Clientset { + return k8sClientFake.NewSimpleClientset(&corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-pod", + Namespace: "default", + }, + Status: corev1.PodStatus{ + PodIP: "", + }, + }) + }, + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + expectEmpty: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client := tt.setup() + logger := testr.New(t) + redisIP := getRedisServerIP(client, logger, tt.redisInfo) + + if tt.expectEmpty { + assert.Empty(t, redisIP, "Expected an empty IP address") + } else { + assert.Equal(t, tt.expectedIP, redisIP, "Expected and actual IP do not match") + } + }) + } +} + +func TestGetRedisHostname(t *testing.T) { + tests := []struct { + name string + redisInfo RedisDetails + redisCluster *redisv1beta2.RedisCluster + role string + expected string + }{ + { + name: "standard configuration", + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mycluster", + Namespace: "default", + }, + }, + role: "master", + expected: "redis-pod.mycluster-master-headless.default.svc", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fqdn := getRedisHostname(tt.redisInfo, tt.redisCluster, tt.role) + assert.Equal(t, tt.expected, fqdn, "FQDN should match the expected output") + }) + } +} + +func TestCreateSingleLeaderRedisCommand(t *testing.T) { + logger := testr.New(t) + cr := &redisv1beta2.RedisCluster{} + cmd := CreateSingleLeaderRedisCommand(logger, cr) + + assert.Equal(t, "redis-cli", cmd[0]) + assert.Equal(t, "CLUSTER", cmd[1]) + assert.Equal(t, "ADDSLOTS", cmd[2]) + + expectedLength := 16384 + 3 + + assert.Equal(t, expectedLength, len(cmd)) + assert.Equal(t, "0", cmd[3]) + assert.Equal(t, "16383", cmd[expectedLength-1]) +} From 608d65a7b2564a734f15c63af5760b860c7053e6 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Sat, 11 Nov 2023 06:19:26 +0530 Subject: [PATCH 2/7] Add TestCreateMultipleLeaderRedisCommand Signed-off-by: Shubham Gupta --- k8sutils/redis.go | 4 +-- k8sutils/redis_test.go | 60 ++++++++++++++++++++++++++++++++++++++++++ mocks/utils/utils.go | 31 ++++++++++++++++++++++ 3 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 mocks/utils/utils.go diff --git a/k8sutils/redis.go b/k8sutils/redis.go index 432681e10..7470f80f7 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -82,7 +82,7 @@ func CreateMultipleLeaderRedisCommand(client kubernetes.Interface, logger logr.L for podCount := 0; podCount < int(replicas); podCount++ { podName := cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(podCount) var address string - if *cr.Spec.ClusterVersion == "v7" { + if cr.Spec.ClusterVersion != nil && *cr.Spec.ClusterVersion == "v7" { address = getRedisHostname(RedisDetails{PodName: podName, Namespace: cr.Namespace}, cr, "leader") + ":6379" } else { address = getRedisServerIP(client, logger, RedisDetails{PodName: podName, Namespace: cr.Namespace}) + ":6379" @@ -91,7 +91,7 @@ func CreateMultipleLeaderRedisCommand(client kubernetes.Interface, logger logr.L } cmd = append(cmd, "--cluster-yes") - logger.V(1).Info("Redis cluster creation command", "CommandBase", cmd[:3], "ClusterVersion", *cr.Spec.ClusterVersion, "Replicas", replicas) + logger.V(1).Info("Redis cluster creation command", "CommandBase", cmd[:3], "Replicas", replicas) return cmd } diff --git a/k8sutils/redis_test.go b/k8sutils/redis_test.go index 3975e43b2..73c3a17d3 100644 --- a/k8sutils/redis_test.go +++ b/k8sutils/redis_test.go @@ -8,11 +8,13 @@ import ( "testing" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + mock_utils "github.com/OT-CONTAINER-KIT/redis-operator/mocks/utils" "github.com/go-logr/logr/testr" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" k8sClientFake "k8s.io/client-go/kubernetes/fake" + "k8s.io/utils/pointer" ) func TestCheckRedisNodePresence(t *testing.T) { @@ -188,3 +190,61 @@ func TestCreateSingleLeaderRedisCommand(t *testing.T) { assert.Equal(t, "0", cmd[3]) assert.Equal(t, "16383", cmd[expectedLength-1]) } + +func TestCreateMultipleLeaderRedisCommand(t *testing.T) { + tests := []struct { + name string + redisCluster *redisv1beta2.RedisCluster + expectedCommands []string + }{ + { + name: "Multiple leaders cluster version v7", + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mycluster", + Namespace: "default", + }, + Spec: redisv1beta2.RedisClusterSpec{ + Size: pointer.Int32(3), + ClusterVersion: pointer.String("v7"), + }, + }, + expectedCommands: []string{ + "redis-cli", "--cluster", "create", + "mycluster-leader-0.mycluster-leader-headless.default.svc:6379", + "mycluster-leader-1.mycluster-leader-headless.default.svc:6379", + "mycluster-leader-2.mycluster-leader-headless.default.svc:6379", + "--cluster-yes", + }, + }, + { + name: "Multiple leaders cluster not v7", + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mycluster", + Namespace: "default", + }, + Spec: redisv1beta2.RedisClusterSpec{ + Size: pointer.Int32(3), + }, + }, + expectedCommands: []string{ + "redis-cli", "--cluster", "create", + "192.168.1.1:6379", + "192.168.1.2:6379", + "192.168.1.3:6379", + "--cluster-yes", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client := mock_utils.CreateFakeClientWithPodIPs(tt.redisCluster) + logger := testr.New(t) + + cmd := CreateMultipleLeaderRedisCommand(client, logger, tt.redisCluster) + assert.Equal(t, tt.expectedCommands, cmd) + }) + } +} diff --git a/mocks/utils/utils.go b/mocks/utils/utils.go new file mode 100644 index 000000000..92a42a050 --- /dev/null +++ b/mocks/utils/utils.go @@ -0,0 +1,31 @@ +package utils + +import ( + "fmt" + "strconv" + + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/fake" +) + +func CreateFakeClientWithPodIPs(cr *redisv1beta2.RedisCluster) *fake.Clientset { + replicas := cr.Spec.GetReplicaCounts("leader") + pods := make([]runtime.Object, replicas) + + for i := 0; i < int(replicas); i++ { + podName := cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(i) + pods[i] = &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: cr.Namespace, + }, + Status: corev1.PodStatus{ + PodIP: fmt.Sprintf("192.168.1.%d", i+1), + }, + } + } + return fake.NewSimpleClientset(pods...) +} From 439312de730f7c63d3dd57765859344bd39c5928 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Sat, 11 Nov 2023 06:31:34 +0530 Subject: [PATCH 3/7] add TestGetRedisTLSArgs Signed-off-by: Shubham Gupta --- k8sutils/redis_test.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/k8sutils/redis_test.go b/k8sutils/redis_test.go index 73c3a17d3..514c14d8d 100644 --- a/k8sutils/redis_test.go +++ b/k8sutils/redis_test.go @@ -248,3 +248,32 @@ func TestCreateMultipleLeaderRedisCommand(t *testing.T) { }) } } + +func TestGetRedisTLSArgs(t *testing.T) { + tests := []struct { + name string + tlsConfig *redisv1beta2.TLSConfig + clientHost string + expected []string + }{ + { + name: "with TLS configuration", + tlsConfig: &redisv1beta2.TLSConfig{}, + clientHost: "redis-host", + expected: []string{"--tls", "--cacert", "/tls/ca.crt", "-h", "redis-host"}, + }, + { + name: "without TLS configuration", + tlsConfig: nil, + clientHost: "redis-host", + expected: []string{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := getRedisTLSArgs(tt.tlsConfig, tt.clientHost) + assert.Equal(t, tt.expected, cmd, "Expected command arguments do not match") + }) + } +} From 653f0506c247b871528c484993a93c21c56ad5c2 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Sat, 11 Nov 2023 06:38:18 +0530 Subject: [PATCH 4/7] createRedisReplicationCommand Signed-off-by: Shubham Gupta --- k8sutils/redis.go | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/k8sutils/redis.go b/k8sutils/redis.go index 7470f80f7..bbc4436f9 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -138,25 +138,32 @@ func getRedisTLSArgs(tlsConfig *redisv1beta2.TLSConfig, clientHost string) []str // createRedisReplicationCommand will create redis replication creation command func createRedisReplicationCommand(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, leaderPod RedisDetails, followerPod RedisDetails) []string { cmd := []string{"redis-cli", "--cluster", "add-node"} - if *cr.Spec.ClusterVersion == "v7" { - cmd = append(cmd, getRedisHostname(followerPod, cr, "follower")+":6379") - cmd = append(cmd, getRedisHostname(leaderPod, cr, "leader")+":6379") + var followerAddress, leaderAddress string + + if cr.Spec.ClusterVersion != nil && *cr.Spec.ClusterVersion == "v7" { + followerAddress = getRedisHostname(followerPod, cr, "follower") + ":6379" + leaderAddress = getRedisHostname(leaderPod, cr, "leader") + ":6379" } else { - cmd = append(cmd, getRedisServerIP(client, logger, followerPod)+":6379") - cmd = append(cmd, getRedisServerIP(client, logger, leaderPod)+":6379") + followerAddress = getRedisServerIP(client, logger, followerPod) + ":6379" + leaderAddress = getRedisServerIP(client, logger, leaderPod) + ":6379" } - cmd = append(cmd, "--cluster-slave") + + cmd = append(cmd, followerAddress, leaderAddress, "--cluster-slave") if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { - logger.Error(err, "Error in getting redis password") + logger.Error(err, "Failed to retrieve Redis password", "Secret", *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name) } - cmd = append(cmd, "-a") - cmd = append(cmd, pass) + cmd = append(cmd, "-a", pass) } + cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, leaderPod.PodName)...) - logger.V(2).Info("Redis replication creation command is", "Command", cmd) + + logger.V(1).Info("Generated Redis replication command", + "FollowerAddress", followerAddress, "LeaderAddress", leaderAddress, + "Command", cmd) + return cmd } From e7392bdc9aa5da69112cba9085e2c8a66f107806 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Sat, 11 Nov 2023 18:59:24 +0530 Subject: [PATCH 5/7] Add test Signed-off-by: Shubham Gupta --- k8sutils/cluster-scaling.go | 14 ++-- k8sutils/redis.go | 36 ++++---- k8sutils/redis_test.go | 161 +++++++++++++++++++++++++++++++++++- 3 files changed, 183 insertions(+), 28 deletions(-) diff --git a/k8sutils/cluster-scaling.go b/k8sutils/cluster-scaling.go index bd7d101a2..b0a384c02 100644 --- a/k8sutils/cluster-scaling.go +++ b/k8sutils/cluster-scaling.go @@ -71,7 +71,7 @@ func ReshardRedisCluster(client kubernetes.Interface, logger logr.Logger, cr *re logger.V(1).Info("Skipped the execution of", "Cmd", cmd) return } - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") } func getRedisClusterSlots(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, nodeID string) string { @@ -170,7 +170,7 @@ func RebalanceRedisClusterEmptyMasters(client kubernetes.Interface, logger logr. cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) logger.V(1).Info("Redis cluster rebalance command is", "Command", cmd) - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-1") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-1") } func CheckIfEmptyMasters(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { @@ -220,7 +220,7 @@ func RebalanceRedisCluster(client kubernetes.Interface, logger logr.Logger, cr * cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) logger.V(1).Info("Redis cluster rebalance command is", "Command", cmd) - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-1") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-1") } // Add redis cluster node would add a node to the existing redis cluster using redis-cli @@ -259,7 +259,7 @@ func AddRedisNodeToCluster(ctx context.Context, client kubernetes.Interface, log cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) logger.V(1).Info("Redis cluster add-node command is", "Command", cmd) - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") } // getAttachedFollowerNodeIDs would return a slice of redis followers attached to a redis leader @@ -330,7 +330,7 @@ func RemoveRedisFollowerNodesFromCluster(ctx context.Context, client kubernetes. cmd = append(cmd, followerNodeID) logger.V(1).Info("Redis cluster follower remove command is", "Command", cmd) - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") cmd = cmd[:len(cmd)-1] } } @@ -375,7 +375,7 @@ func RemoveRedisNodeFromCluster(ctx context.Context, client kubernetes.Interface if getRedisClusterSlots(ctx, client, logger, cr, removePodNodeID) != "0" { logger.V(1).Info("Skipping execution remove leader not empty", "cmd", cmd) } - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") } // verifyLeaderPod return true if the pod is leader/master @@ -430,5 +430,5 @@ func ClusterFailover(ctx context.Context, client kubernetes.Interface, logger lo cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, slavePodName)...) logger.V(1).Info("Redis cluster failover command is", "Command", cmd) - executeCommand(cr, cmd, slavePodName) + executeCommand(client, logger, cr, cmd, slavePodName) } diff --git a/k8sutils/redis.go b/k8sutils/redis.go index bbc4436f9..51cb0a4e3 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -120,7 +120,7 @@ func ExecuteRedisClusterCommand(ctx context.Context, client kubernetes.Interface } cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) logger.V(1).Info("Redis cluster creation command is", "Command", cmd) - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") } func getRedisTLSArgs(tlsConfig *redisv1beta2.TLSConfig, clientHost string) []string { @@ -197,7 +197,7 @@ func ExecuteRedisReplicationCommand(ctx context.Context, client kubernetes.Inter continue } if pong == "PONG" { - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") } else { logger.V(1).Info("Skipping execution of command due to failed Redis ping", "Follower.Pod", followerPod) } @@ -357,23 +357,17 @@ func configureRedisClient(client kubernetes.Interface, logger logr.Logger, cr *r } // executeCommand will execute the commands in pod -func executeCommand(cr *redisv1beta2.RedisCluster, cmd []string, podName string) { +func executeCommand(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, cmd []string, podName string) { var ( execOut bytes.Buffer execErr bytes.Buffer ) - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return - } config, err := GenerateK8sConfig() if err != nil { logger.Error(err, "Could not find pod to execute") return } - targetContainer, pod := getContainerID(cr, podName) + targetContainer, pod := getContainerID(client, logger, cr, podName) if targetContainer < 0 { logger.Error(err, "Could not find pod to execute") return @@ -405,26 +399,30 @@ func executeCommand(cr *redisv1beta2.RedisCluster, cmd []string, podName string) } // getContainerID will return the id of container from pod -func getContainerID(cr *redisv1beta2.RedisCluster, podName string) (int, *corev1.Pod) { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return -1, nil - } +func getContainerID(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, podName string) (int, *corev1.Pod) { pod, err := client.CoreV1().Pods(cr.Namespace).Get(context.TODO(), podName, metav1.GetOptions{}) if err != nil { - logger.Error(err, "Could not get pod info") + logger.Error(err, "Could not get pod info", "Pod Name", podName, "Namespace", cr.Namespace) + return -1, nil } + logger.Info("Pod info retrieved successfully", "Pod Name", podName, "Namespace", cr.Namespace) + targetContainer := -1 for containerID, tr := range pod.Spec.Containers { - logger.V(1).Info("Pod Counted successfully", "Count", containerID, "Container Name", tr.Name) + logger.V(1).Info("Inspecting container", "Pod Name", podName, "Container ID", containerID, "Container Name", tr.Name) if tr.Name == cr.ObjectMeta.Name+"-leader" { targetContainer = containerID + logger.Info("Leader container found", "Container ID", containerID, "Container Name", tr.Name) break } } + + if targetContainer == -1 { + logger.Info("Leader container not found in pod", "Pod Name", podName) + return -1, nil + } + return targetContainer, pod } diff --git a/k8sutils/redis_test.go b/k8sutils/redis_test.go index 514c14d8d..864eeea16 100644 --- a/k8sutils/redis_test.go +++ b/k8sutils/redis_test.go @@ -1,4 +1,3 @@ -// checkRedisNodePresence package k8sutils import ( @@ -218,7 +217,7 @@ func TestCreateMultipleLeaderRedisCommand(t *testing.T) { }, }, { - name: "Multiple leaders cluster not v7", + name: "Multiple leaders cluster without version v7", redisCluster: &redisv1beta2.RedisCluster{ ObjectMeta: metav1.ObjectMeta{ Name: "mycluster", @@ -277,3 +276,161 @@ func TestGetRedisTLSArgs(t *testing.T) { }) } } + +// func TestCreateRedisReplicationCommand(t *testing.T) { +// tests := []struct { +// name string +// redisCluster *redisv1beta2.RedisCluster +// leaderPod RedisDetails +// followerPod RedisDetails +// expectedCommand []string +// }{ +// { +// name: "Test case with cluster version v7", +// redisCluster: &redisv1beta2.RedisCluster{ +// ObjectMeta: metav1.ObjectMeta{ +// Name: "redis-cluster", +// Namespace: "default", +// }, +// Spec: redisv1beta2.RedisClusterSpec{ +// Size: pointer.Int32(3), +// ClusterVersion: pointer.String("v7"), +// }, +// }, +// leaderPod: RedisDetails{ +// PodName: "redis-cluster-leader-0", +// Namespace: "default", +// }, +// followerPod: RedisDetails{ +// PodName: "redis-cluster-follower-0", +// Namespace: "default", +// }, +// expectedCommand: []string{}, +// }, +// { +// name: "Test case without cluster version v7", +// redisCluster: &redisv1beta2.RedisCluster{ +// ObjectMeta: metav1.ObjectMeta{ +// Name: "mycluster", +// Namespace: "default", +// }, +// Spec: redisv1beta2.RedisClusterSpec{ +// Size: pointer.Int32(3), +// }, +// }, +// leaderPod: RedisDetails{ +// PodName: "redis-cluster-leader-0", +// Namespace: "default", +// }, +// followerPod: RedisDetails{ +// PodName: "redis-cluster-follower-0", +// Namespace: "default", +// }, +// expectedCommand: []string{}, +// }, +// } + +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// client := mock_utils.CreateFakeClientWithPodIPs(tt.redisCluster) +// logger := testr.New(t) + +// // Call the function under test +// cmd := createRedisReplicationCommand(client, logger, tt.redisCluster, tt.leaderPod, tt.followerPod) + +// // Assert the command is as expected using testify +// assert.Equal(t, tt.expectedCommand, cmd) +// }) +// } +// } + +func TestGetContainerID(t *testing.T) { + tests := []struct { + name string + setupPod *corev1.Pod + redisCluster *redisv1beta2.RedisCluster + expectedID int + expectError bool + }{ + { + name: "Successful retrieval of leader container", + setupPod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster-leader-0", + Namespace: "default", + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "redis-cluster-leader", + }, + { + Name: "another-container", + }, + }, + }, + }, + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + }, + expectedID: 0, + expectError: false, + }, + { + name: "Pod not found", + setupPod: &corev1.Pod{}, + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + }, + expectedID: -1, + expectError: true, + }, + { + name: "Leader container not found in the pod", + setupPod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster-leader-0", + Namespace: "default", + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "non-leader-container", + }, + }, + }, + }, + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + }, + expectedID: -1, + expectError: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + client := k8sClientFake.NewSimpleClientset(test.setupPod) + logger := testr.New(t) + id, pod := getContainerID(client, logger, test.redisCluster, test.setupPod.Name) + if test.expectError { + assert.Nil(t, pod, "Expected no pod but got one") + assert.Equal(t, test.expectedID, id, "Expected ID does not match") + } else { + assert.NotNil(t, pod, "Expected a pod but got none") + assert.Equal(t, test.expectedID, id, "Expected ID does not match") + assert.Equal(t, test.setupPod.Name, pod.GetName(), "Pod names do not match") + assert.Equal(t, test.setupPod.Namespace, pod.GetNamespace(), "Pod namespaces do not match") + } + }) + } +} From 2b6ad4b828500a18e621029d79625eedcd3d83fb Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Sat, 11 Nov 2023 19:25:47 +0530 Subject: [PATCH 6/7] fix Signed-off-by: Shubham Gupta --- k8sutils/redis_test.go | 137 ++++++++++++++++++++++------------------- mocks/utils/utils.go | 36 ++++++++++- 2 files changed, 108 insertions(+), 65 deletions(-) diff --git a/k8sutils/redis_test.go b/k8sutils/redis_test.go index 864eeea16..26628290d 100644 --- a/k8sutils/redis_test.go +++ b/k8sutils/redis_test.go @@ -239,7 +239,7 @@ func TestCreateMultipleLeaderRedisCommand(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - client := mock_utils.CreateFakeClientWithPodIPs(tt.redisCluster) + client := mock_utils.CreateFakeClientWithPodIPs_LeaderPods(tt.redisCluster) logger := testr.New(t) cmd := CreateMultipleLeaderRedisCommand(client, logger, tt.redisCluster) @@ -277,72 +277,81 @@ func TestGetRedisTLSArgs(t *testing.T) { } } -// func TestCreateRedisReplicationCommand(t *testing.T) { -// tests := []struct { -// name string -// redisCluster *redisv1beta2.RedisCluster -// leaderPod RedisDetails -// followerPod RedisDetails -// expectedCommand []string -// }{ -// { -// name: "Test case with cluster version v7", -// redisCluster: &redisv1beta2.RedisCluster{ -// ObjectMeta: metav1.ObjectMeta{ -// Name: "redis-cluster", -// Namespace: "default", -// }, -// Spec: redisv1beta2.RedisClusterSpec{ -// Size: pointer.Int32(3), -// ClusterVersion: pointer.String("v7"), -// }, -// }, -// leaderPod: RedisDetails{ -// PodName: "redis-cluster-leader-0", -// Namespace: "default", -// }, -// followerPod: RedisDetails{ -// PodName: "redis-cluster-follower-0", -// Namespace: "default", -// }, -// expectedCommand: []string{}, -// }, -// { -// name: "Test case without cluster version v7", -// redisCluster: &redisv1beta2.RedisCluster{ -// ObjectMeta: metav1.ObjectMeta{ -// Name: "mycluster", -// Namespace: "default", -// }, -// Spec: redisv1beta2.RedisClusterSpec{ -// Size: pointer.Int32(3), -// }, -// }, -// leaderPod: RedisDetails{ -// PodName: "redis-cluster-leader-0", -// Namespace: "default", -// }, -// followerPod: RedisDetails{ -// PodName: "redis-cluster-follower-0", -// Namespace: "default", -// }, -// expectedCommand: []string{}, -// }, -// } +func TestCreateRedisReplicationCommand(t *testing.T) { + tests := []struct { + name string + redisCluster *redisv1beta2.RedisCluster + leaderPod RedisDetails + followerPod RedisDetails + expectedCommand []string + }{ + { + name: "Test case with cluster version v7", + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + Spec: redisv1beta2.RedisClusterSpec{ + Size: pointer.Int32(3), + ClusterVersion: pointer.String("v7"), + }, + }, + leaderPod: RedisDetails{ + PodName: "redis-cluster-leader-0", + Namespace: "default", + }, + followerPod: RedisDetails{ + PodName: "redis-cluster-follower-0", + Namespace: "default", + }, + expectedCommand: []string{ + "redis-cli", "--cluster", "add-node", + "redis-cluster-follower-0.redis-cluster-follower-headless.default.svc:6379", + "redis-cluster-leader-0.redis-cluster-leader-headless.default.svc:6379", + "--cluster-slave", + }, + }, + { + name: "Test case without cluster version v7", + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + Spec: redisv1beta2.RedisClusterSpec{ + Size: pointer.Int32(3), + }, + }, + leaderPod: RedisDetails{ + PodName: "redis-cluster-leader-0", + Namespace: "default", + }, + followerPod: RedisDetails{ + PodName: "redis-cluster-follower-0", + Namespace: "default", + }, + expectedCommand: []string{ + "redis-cli", "--cluster", "add-node", + "192.168.2.1:6379", + "192.168.1.1:6379", + "--cluster-slave", + }, + }, + } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// client := mock_utils.CreateFakeClientWithPodIPs(tt.redisCluster) -// logger := testr.New(t) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client := mock_utils.CreateFakeClientWithPodIPs(tt.redisCluster) + logger := testr.New(t) -// // Call the function under test -// cmd := createRedisReplicationCommand(client, logger, tt.redisCluster, tt.leaderPod, tt.followerPod) + cmd := createRedisReplicationCommand(client, logger, tt.redisCluster, tt.leaderPod, tt.followerPod) -// // Assert the command is as expected using testify -// assert.Equal(t, tt.expectedCommand, cmd) -// }) -// } -// } + // Assert the command is as expected using testify + assert.Equal(t, tt.expectedCommand, cmd) + }) + } +} func TestGetContainerID(t *testing.T) { tests := []struct { diff --git a/mocks/utils/utils.go b/mocks/utils/utils.go index 92a42a050..d279af3d4 100644 --- a/mocks/utils/utils.go +++ b/mocks/utils/utils.go @@ -11,7 +11,7 @@ import ( "k8s.io/client-go/kubernetes/fake" ) -func CreateFakeClientWithPodIPs(cr *redisv1beta2.RedisCluster) *fake.Clientset { +func CreateFakeClientWithPodIPs_LeaderPods(cr *redisv1beta2.RedisCluster) *fake.Clientset { replicas := cr.Spec.GetReplicaCounts("leader") pods := make([]runtime.Object, replicas) @@ -29,3 +29,37 @@ func CreateFakeClientWithPodIPs(cr *redisv1beta2.RedisCluster) *fake.Clientset { } return fake.NewSimpleClientset(pods...) } + +func CreateFakeClientWithPodIPs(cr *redisv1beta2.RedisCluster) *fake.Clientset { + leaderReplicas := cr.Spec.GetReplicaCounts("leader") + followerReplicas := cr.Spec.GetReplicaCounts("follower") + pods := make([]runtime.Object, leaderReplicas+followerReplicas) + + for i := 0; i < int(leaderReplicas); i++ { + podName := cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(i) + pods[i] = &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: cr.Namespace, + }, + Status: corev1.PodStatus{ + PodIP: fmt.Sprintf("192.168.1.%d", i+1), + }, + } + } + for i := 0; i < int(followerReplicas); i++ { + podName := cr.ObjectMeta.Name + "-follower-" + strconv.Itoa(i) + // Adjust the index to place follower pods after leader pods + pods[i+int(leaderReplicas)] = &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: cr.Namespace, + }, + Status: corev1.PodStatus{ + PodIP: fmt.Sprintf("192.168.2.%d", i+1), + }, + } + } + + return fake.NewSimpleClientset(pods...) +} From 34413cd55654052ea6ba1292b5fc765002b10903 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Sat, 11 Nov 2023 19:54:20 +0530 Subject: [PATCH 7/7] add Signed-off-by: Shubham Gupta --- mocks/utils/utils.go | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/mocks/utils/utils.go b/mocks/utils/utils.go index d279af3d4..6f9c33b99 100644 --- a/mocks/utils/utils.go +++ b/mocks/utils/utils.go @@ -49,7 +49,6 @@ func CreateFakeClientWithPodIPs(cr *redisv1beta2.RedisCluster) *fake.Clientset { } for i := 0; i < int(followerReplicas); i++ { podName := cr.ObjectMeta.Name + "-follower-" + strconv.Itoa(i) - // Adjust the index to place follower pods after leader pods pods[i+int(leaderReplicas)] = &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: podName, @@ -63,3 +62,46 @@ func CreateFakeClientWithPodIPs(cr *redisv1beta2.RedisCluster) *fake.Clientset { return fake.NewSimpleClientset(pods...) } + +func CreateFakeClientWithSecrets(cr *redisv1beta2.RedisCluster, secretName, secretKey, secretValue string) *fake.Clientset { + leaderReplicas := cr.Spec.GetReplicaCounts("leader") + followerReplicas := cr.Spec.GetReplicaCounts("follower") + pods := make([]runtime.Object, leaderReplicas+followerReplicas) + + for i := 0; i < int(leaderReplicas); i++ { + podName := cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(i) + pods[i] = &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: cr.Namespace, + }, + Status: corev1.PodStatus{ + PodIP: fmt.Sprintf("192.168.1.%d", i+1), + }, + } + } + for i := 0; i < int(followerReplicas); i++ { + podName := cr.ObjectMeta.Name + "-follower-" + strconv.Itoa(i) + pods[i+int(leaderReplicas)] = &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: cr.Namespace, + }, + Status: corev1.PodStatus{ + PodIP: fmt.Sprintf("192.168.2.%d", i+1), + }, + } + } + + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: cr.Namespace, + }, + Data: map[string][]byte{ + secretKey: []byte(secretValue), + }, + } + + return fake.NewSimpleClientset(append(pods, secret)...) +}