From ca7fe722a260fc4b8ff953badf6344ca1ea02741 Mon Sep 17 00:00:00 2001 From: Artur Zheludkov Date: Thu, 11 Jan 2024 14:56:07 -0500 Subject: [PATCH] Add in HaProxy slave redis in bootstrap mode --- operator/redisfailover/service/generator.go | 32 +++++++ .../redisfailover/service/generator_test.go | 94 +++++++++++++++++-- 2 files changed, 117 insertions(+), 9 deletions(-) diff --git a/operator/redisfailover/service/generator.go b/operator/redisfailover/service/generator.go index d7c1cbe5e..dff3f4574 100644 --- a/operator/redisfailover/service/generator.go +++ b/operator/redisfailover/service/generator.go @@ -186,6 +186,26 @@ func generateHAProxyConfigmap(rf *redisfailoverv1.RedisFailover, labels map[stri server-template redis %d _redis._tcp.%s.%s.svc.cluster.local:%d check inter 1s resolvers k8s init-addr none `, port, rf.Spec.Redis.Replicas, redisName, namespace, port) + if rf.Spec.BootstrapNode != nil && rf.Spec.BootstrapNode.Port != rf.Spec.Redis.Port.ToString() { + + portInt, _ := strconv.Atoi(rf.Spec.BootstrapNode.Port) + haproxyCfg += fmt.Sprintf(` + frontend redis-slave + bind *:%d + default_backend redis-slave + + backend redis-slave + mode tcp + balance first + option tcp-check + tcp-check send info\ replication\r\n + tcp-check expect string role:slave + server-template redis %d _redis._tcp.%s.%s.svc.cluster.local:%d check inter 1s resolvers k8s init-addr none +`, + portInt, rf.Spec.Redis.Replicas, redisName, namespace, port) + + } + if rf.Spec.Haproxy.CustomConfig != "" { haproxyCfg = rf.Spec.Haproxy.CustomConfig } @@ -263,6 +283,18 @@ func generateHAProxyService(rf *redisfailoverv1.RedisFailover, labels map[string }, } + if rf.Spec.BootstrapNode != nil && rf.Spec.BootstrapNode.Port != rf.Spec.Redis.Port.ToString() { + + portInt, _ := strconv.Atoi(rf.Spec.BootstrapNode.Port) + additionalPort := corev1.ServicePort{ + Name: "redis-slave", + Port: int32(portInt), + TargetPort: intstr.FromInt(int(portInt)), + Protocol: "TCP", + } + spec.Ports = append(spec.Ports, additionalPort) + } + serviceSettings := rf.Spec.Haproxy.Service if serviceSettings != nil { if serviceSettings.ClusterIP != "" { diff --git a/operator/redisfailover/service/generator_test.go b/operator/redisfailover/service/generator_test.go index bb89f5b12..74d321f8b 100644 --- a/operator/redisfailover/service/generator_test.go +++ b/operator/redisfailover/service/generator_test.go @@ -2,6 +2,7 @@ package service_test import ( "fmt" + "strconv" "testing" "github.com/stretchr/testify/assert" @@ -1297,12 +1298,15 @@ func TestRedisService(t *testing.T) { func TestHaproxyService(t *testing.T) { haproxyName := "redis-haproxy" portName := "redis-master" - defaultRedisPort := redisfailoverv1.Port(6379) + slaveRedisPortName := "redis-slave" + redisPort := 6379 + redisSlavePort := 6389 + defaultRedisPort := redisfailoverv1.Port(redisPort) + defaultRedisSlavePort := redisfailoverv1.Port(redisSlavePort) customClusterIP := "10.1.1.100" tests := []struct { name string - rfName string - rfNamespace string + rfBootstrap redisfailoverv1.BootstrapSettings rfLabels map[string]string rfAnnotations map[string]string rfRedisPort redisfailoverv1.Port @@ -1374,6 +1378,79 @@ func TestHaproxyService(t *testing.T) { }, }, }, + }, { + name: "with bootstrapSettings without Port", + rfRedisPort: defaultRedisPort, + rfBootstrap: redisfailoverv1.BootstrapSettings{ + Host: "redis", + Port: strconv.Itoa(redisPort), + }, + expectedService: corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: haproxyName, + Namespace: namespace, + OwnerReferences: []metav1.OwnerReference{ + { + Name: "testing", + }, + }, + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeClusterIP, + Selector: map[string]string{ + "app.kubernetes.io/component": "redis", + "redisfailovers.databases.spotahome.com/component": "haproxy", + }, + Ports: []corev1.ServicePort{ + { + Name: portName, + Port: defaultRedisPort.ToInt32(), + TargetPort: intstr.FromInt(int(defaultRedisPort)), + Protocol: corev1.ProtocolTCP, + }, + }, + }, + }, + }, + { + name: "with bootstrapSettings and with different Port", + rfRedisPort: defaultRedisPort, + rfBootstrap: redisfailoverv1.BootstrapSettings{ + Host: "redis", + Port: defaultRedisSlavePort.ToString(), + }, + expectedService: corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: haproxyName, + Namespace: namespace, + OwnerReferences: []metav1.OwnerReference{ + { + Name: "testing", + }, + }, + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeClusterIP, + Selector: map[string]string{ + "app.kubernetes.io/component": "redis", + "redisfailovers.databases.spotahome.com/component": "haproxy", + }, + Ports: []corev1.ServicePort{ + { + Name: portName, + Port: defaultRedisPort.ToInt32(), + TargetPort: intstr.FromInt(int(defaultRedisPort)), + Protocol: corev1.ProtocolTCP, + }, + { + Name: slaveRedisPortName, + Port: defaultRedisSlavePort.ToInt32(), + TargetPort: intstr.FromInt(int(defaultRedisSlavePort)), + Protocol: corev1.ProtocolTCP, + }, + }, + }, + }, }, } @@ -1383,16 +1460,15 @@ func TestHaproxyService(t *testing.T) { // Generate a default RedisFailover and attaching the required annotations rf := generateRF() - if test.rfName != "" { - rf.Name = test.rfName - } - if test.rfNamespace != "" { - rf.Namespace = test.rfNamespace - } + rf.Spec.Redis.ServiceAnnotations = test.rfAnnotations rf.Spec.Redis.Port = test.rfRedisPort rf.Spec.Haproxy = &test.haproxy + if test.rfBootstrap.Host != "" { + rf.Spec.BootstrapNode = &test.rfBootstrap + } + generatedService := corev1.Service{} ms := &mK8SService.Services{}