Skip to content

Commit

Permalink
Failover volume mount should also use custom map if configured
Browse files Browse the repository at this point in the history
  • Loading branch information
sergicastro committed Nov 13, 2024
1 parent 05da6ca commit af2af33
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ package failover

import (
"errors"
"strconv"

core "k8s.io/api/core/v1"
v1 "reactive-tech.io/kubegres/api/v1"
"reactive-tech.io/kubegres/controllers/ctx"
"reactive-tech.io/kubegres/controllers/operation"
"reactive-tech.io/kubegres/controllers/states"
"reactive-tech.io/kubegres/controllers/states/statefulset"
"strconv"
)

type PrimaryToReplicaFailOver struct {
Expand Down Expand Up @@ -244,9 +245,9 @@ func (r *PrimaryToReplicaFailOver) promoteReplicaToPrimary(newPrimary statefulse
newPrimary.StatefulSet.Labels["replicationRole"] = ctx.PrimaryRoleName
newPrimary.StatefulSet.Spec.Template.Labels["replicationRole"] = ctx.PrimaryRoleName
volumeMount := core.VolumeMount{
Name: "base-config",
Name: r.resourcesStates.Config.ConfigLocations.PromoteReplica,
MountPath: "/tmp/promote_replica_to_primary.sh",
SubPath: "promote_replica_to_primary.sh",
SubPath: states.ConfigMapDataKeyPromoteReplica,
}

initContainer := &newPrimary.StatefulSet.Spec.Template.Spec.InitContainers[0]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ func (r *VolumeSpecEnforcer) CheckForSpecDifference(statefulSet *apps.StatefulSe

if hasInitContainer && !r.compareVolumeMounts(currentCustomVolumeMountsInit, expectedCustomVolumeMounts) {
return StatefulSetSpecDifference{
SpecName: "Volume.VolumeMounts",
SpecName: "Volume.VolumeMounts[initContainer]",
Current: r.volumeMountsToString(currentCustomVolumeMountsInit),
Expected: r.volumeMountsToString(expectedCustomVolumeMounts),
}
}

if !r.compareVolumeMounts(currentCustomVolumeMounts, expectedCustomVolumeMounts) {
return StatefulSetSpecDifference{
SpecName: "Volume.VolumeMounts",
SpecName: "Volume.VolumeMounts[container]",
Current: r.volumeMountsToString(currentCustomVolumeMounts),
Expected: r.volumeMountsToString(expectedCustomVolumeMounts),
}
Expand Down
81 changes: 80 additions & 1 deletion test/primary_failure_and_recovery_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ var _ = Describe("Primary instances is not available, checking recovery works",
namespace := resourceConfigs.DefaultNamespace
test.resourceRetriever = util.CreateTestResourceRetriever(k8sClientTest, namespace)
test.resourceCreator = util.CreateTestResourceCreator(k8sClientTest, test.resourceRetriever, namespace)
test.resourceCreator.CreateConfigMapWithPromoteReplicaScript()
test.connectionPrimaryDb = util.InitDbConnectionDbUtil(test.resourceCreator, resourceConfigs.KubegresResourceName, resourceConfigs.ServiceToSqlQueryPrimaryDbNodePort, true)
test.connectionReplicaDb = util.InitDbConnectionDbUtil(test.resourceCreator, resourceConfigs.KubegresResourceName, resourceConfigs.ServiceToSqlQueryReplicaDbNodePort, false)
})
Expand Down Expand Up @@ -119,7 +120,7 @@ var _ = Describe("Primary instances is not available, checking recovery works",

Context("GIVEN Kubegres with 1 primary and 2 replicas AND primary is deleted", func() {

It("THEN the failover should take place with a replica becoming primary AND a new replica created AND existing data available", func() {
It("THEN the failover should take place with a replica becoming primary AND a new replica created AND existing data available, twice", func() {

log.Print("START OF: Test 'GIVEN Kubegres with 1 primary and 2 replicas AND primary is deleted'")

Expand All @@ -137,6 +138,23 @@ var _ = Describe("Primary instances is not available, checking recovery works",
test.GivenUserAddedInPrimaryDb()
expectedNbreUsers++

// First failover

test.whenPrimaryIsDeleted()

test.thenPodsStatesShouldBe(1, 2)

test.ThenPrimaryDbContainsExpectedNbreUsers(expectedNbreUsers)
test.ThenReplicaDbContainsExpectedNbreUsers(expectedNbreUsers)

test.GivenUserAddedInPrimaryDb()
expectedNbreUsers++

test.ThenPrimaryDbContainsExpectedNbreUsers(expectedNbreUsers)
test.ThenReplicaDbContainsExpectedNbreUsers(expectedNbreUsers)

// Second failover

test.whenPrimaryIsDeleted()

test.thenPodsStatesShouldBe(1, 2)
Expand All @@ -154,6 +172,61 @@ var _ = Describe("Primary instances is not available, checking recovery works",
})
})

Context("GIVEN Kubegres with 1 primary and 2 replicas using custom-configs map AND primary is deleted", func() {

It("THEN the failover should take place with a replica becoming primary AND a new replica created AND existing data available, twice", func() {

log.Print("START OF: Test 'GIVEN Kubegres with 1 primary and 2 replicas using custom-configs map AND primary is deleted'")

test.givenNewKubegresSpecIsSetToWithCustomConfigs(3)

test.whenKubegresIsCreated()

test.thenPodsStatesShouldBe(1, 2)

expectedNbreUsers := 0

test.GivenUserAddedInPrimaryDb()
expectedNbreUsers++

test.GivenUserAddedInPrimaryDb()
expectedNbreUsers++

// First failover

test.whenPrimaryIsDeleted()

test.thenPodsStatesShouldBe(1, 2)

test.ThenPrimaryDbContainsExpectedNbreUsers(expectedNbreUsers)
test.ThenReplicaDbContainsExpectedNbreUsers(expectedNbreUsers)

test.GivenUserAddedInPrimaryDb()
expectedNbreUsers++

test.ThenPrimaryDbContainsExpectedNbreUsers(expectedNbreUsers)
test.ThenReplicaDbContainsExpectedNbreUsers(expectedNbreUsers)

// Second failover

test.whenPrimaryIsDeleted()

test.thenPodsStatesShouldBe(1, 2)

test.ThenPrimaryDbContainsExpectedNbreUsers(expectedNbreUsers)
test.ThenReplicaDbContainsExpectedNbreUsers(expectedNbreUsers)

test.GivenUserAddedInPrimaryDb()
expectedNbreUsers++

test.ThenPrimaryDbContainsExpectedNbreUsers(expectedNbreUsers)
test.ThenReplicaDbContainsExpectedNbreUsers(expectedNbreUsers)

log.Print("END OF: Test 'GIVEN Kubegres with 1 primary and 2 replicas using custom-configs map AND primary is deleted'")
})

})

})

type PrimaryFailureAndRecoveryTest struct {
Expand All @@ -171,6 +244,12 @@ func (r *PrimaryFailureAndRecoveryTest) givenNewKubegresSpecIsSetTo(specNbreRepl
r.kubegresResource.Spec.Replicas = &specNbreReplicas
}

func (r *PrimaryFailureAndRecoveryTest) givenNewKubegresSpecIsSetToWithCustomConfigs(specNbreReplicas int32) {
r.kubegresResource = resourceConfigs.LoadKubegresYaml()
r.kubegresResource.Spec.Replicas = &specNbreReplicas
r.kubegresResource.Spec.CustomConfig = resourceConfigs.CustomConfigMapWithPromoteReplicaScriptResourceName
}

func (r *PrimaryFailureAndRecoveryTest) whenKubegresIsCreated() {
r.resourceCreator.CreateKubegres(r.kubegresResource)
}
Expand Down
3 changes: 3 additions & 0 deletions test/resourceConfigs/ConfigForTest.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,7 @@ const (

CustomConfigMapWithPostgresConfAndWalLevelSetToLogicalResourceName = "config-with-postgres-conf-wal-level-to-logical"
CustomConfigMapWithPostgresConfAndWalLevelSetToLogicalYamlFile = "resourceConfigs/customConfig/configMap_with_postgres_conf_and_wal_level_to_logical.yaml"

CustomConfigMapWithPromoteReplicaScriptResourceName = "config-with-promote-replica-script"
CustomConfigMapWithPromoteReplicaScriptYamlFile = "resourceConfigs/customConfig/configMap_with_promote_replica_script.yaml"
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: config-with-promote-replica-script
namespace: default
labels:
environment: acceptancetesting

data:

promote_replica_to_primary.sh: |
#!/bin/bash
set -e
dt=$(date '+%d/%m/%Y %H:%M:%S');
echo "$dt - Attempting to promote a Replica PostgreSql to Primary...";
standbyFilePath="$PGDATA/standby.signal"
if [ ! -f "$standbyFilePath" ]; then
echo "$dt - Skipping as this PostgreSql is already a Primary since the file '$standbyFilePath' does not exist."
exit 0
fi
promotionTriggerFilePath="$PGDATA/promote_replica_to_primary.log"
if [ -f "$promotionTriggerFilePath" ]; then
echo "$dt - Skipping as the promotion trigger file '$promotionTriggerFilePath' already exists"
exit 0
fi
echo "$dt - Promoting by creating the promotion trigger file: '$promotionTriggerFilePath'"
touch $promotionTriggerFilePath
2 changes: 1 addition & 1 deletion test/spec_customConfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ var _ = Describe("Setting Kubegres specs 'customConfig'", Label("group:2"), func
test.resourceCreator.CreateConfigMapWithPgHbaConf()
test.resourceCreator.CreateConfigMapWithPostgresConf()
test.resourceCreator.CreateConfigMapWithPrimaryInitScript()
test.resourceCreator.CreateConfigMapWithPromoteReplicaScript()
})

AfterEach(func() {
Expand Down Expand Up @@ -344,7 +345,6 @@ var _ = Describe("Setting Kubegres specs 'customConfig'", Label("group:2"), func
log.Print("END OF: Test 'GIVEN new Kubegres is created with backUp enabled and spec 'customConfig' set to base-config AND later it is updated to a configMap containing data-key 'backup_database.sh''")
})
})

})

type SpecCustomConfigTest struct {
Expand Down
7 changes: 7 additions & 0 deletions test/util/TestResourceCreator.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,13 @@ func (r *TestResourceCreator) CreateConfigMapWithPostgresConfAndWalLevelSetToLog
r.createResourceFromYaml("Custom ConfigMap with postgres conf and wal_level=logical", resourceConfigs2.CustomConfigMapWithPostgresConfAndWalLevelSetToLogicalResourceName, &existingResource, &resourceToCreate)
}

func (r *TestResourceCreator) CreateConfigMapWithPromoteReplicaScript() {
existingResource := v1.ConfigMap{}
resourceToCreate := resourceConfigs2.LoadCustomConfigMapYaml(resourceConfigs2.CustomConfigMapWithPromoteReplicaScriptYamlFile)
resourceToCreate.Namespace = r.namespace
r.createResourceFromYaml("Custom ConfigMap with promote replica script", resourceConfigs2.CustomConfigMapWithPromoteReplicaScriptResourceName, &existingResource, &resourceToCreate)
}

func (r *TestResourceCreator) CreateNamespace() {
if r.namespace == resourceConfigs2.DefaultNamespace {
return
Expand Down

0 comments on commit af2af33

Please sign in to comment.