Skip to content

Commit b431f35

Browse files
authored
Changes in update database configuration to detect if the database was configured (#2237)
* Changes in update database configuration to detect if the database was configured
1 parent 6ae55c0 commit b431f35

9 files changed

+313
-140
lines changed

controllers/cluster_controller.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,10 @@ func (r *FoundationDBClusterReconciler) getLockClient(logger logr.Logger, cluste
469469

470470
// takeLock attempts to acquire a lock.
471471
func (r *FoundationDBClusterReconciler) takeLock(logger logr.Logger, cluster *fdbv1beta2.FoundationDBCluster, action string) error {
472+
if !cluster.ShouldUseLocks() {
473+
return nil
474+
}
475+
472476
logger.Info("Taking lock on cluster", "action", action)
473477
lockClient, err := r.getLockClient(logger, cluster)
474478
if err != nil {

controllers/cluster_controller_test.go

Lines changed: 0 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,96 +1033,6 @@ var _ = Describe("cluster_controller", func() {
10331033
})
10341034
})
10351035

1036-
Context("with a configuration change", func() {
1037-
var adminClient *mock.AdminClient
1038-
BeforeEach(func() {
1039-
adminClient, err = mock.NewMockAdminClientUncast(cluster, k8sClient)
1040-
Expect(err).NotTo(HaveOccurred())
1041-
1042-
status, err := adminClient.GetStatus()
1043-
Expect(err).NotTo(HaveOccurred())
1044-
Expect(status.Cluster.DatabaseConfiguration.RedundancyMode).To(Equal(fdbv1beta2.RedundancyModeDouble))
1045-
1046-
cluster.Spec.DatabaseConfiguration.RedundancyMode = fdbv1beta2.RedundancyModeTriple
1047-
1048-
status, err = adminClient.GetStatus()
1049-
Expect(err).NotTo(HaveOccurred())
1050-
Expect(status.Cluster.DatabaseConfiguration.RedundancyMode).To(Equal(fdbv1beta2.RedundancyModeDouble))
1051-
})
1052-
1053-
Context("with changes enabled", func() {
1054-
BeforeEach(func() {
1055-
err = k8sClient.Update(context.TODO(), cluster)
1056-
Expect(err).NotTo(HaveOccurred())
1057-
})
1058-
1059-
It("should configure the database", func() {
1060-
Expect(adminClient.DatabaseConfiguration.RedundancyMode).To(Equal(fdbv1beta2.RedundancyModeTriple))
1061-
})
1062-
})
1063-
1064-
Context("with a change to the log version", func() {
1065-
BeforeEach(func() {
1066-
cluster.Spec.DatabaseConfiguration.LogVersion = 3
1067-
cluster.Spec.DatabaseConfiguration.RedundancyMode = fdbv1beta2.RedundancyModeDouble
1068-
generationGap = 1
1069-
err = k8sClient.Update(context.TODO(), cluster)
1070-
Expect(err).NotTo(HaveOccurred())
1071-
})
1072-
1073-
It("should configure the database", func() {
1074-
Expect(adminClient.DatabaseConfiguration.RedundancyMode).To(Equal(fdbv1beta2.RedundancyModeDouble))
1075-
Expect(adminClient.DatabaseConfiguration.LogVersion).To(Equal(3))
1076-
})
1077-
})
1078-
1079-
Context("with a change to the log version that is not set in the spec", func() {
1080-
BeforeEach(func() {
1081-
cluster.Spec.DatabaseConfiguration.RedundancyMode = fdbv1beta2.RedundancyModeDouble
1082-
cluster.Spec.SeedConnectionString = "touch"
1083-
1084-
configuration := cluster.DesiredDatabaseConfiguration()
1085-
configuration.LogVersion = 3
1086-
err = adminClient.ConfigureDatabase(configuration, false)
1087-
Expect(err).NotTo(HaveOccurred())
1088-
1089-
generationGap = 1
1090-
err = k8sClient.Update(context.TODO(), cluster)
1091-
Expect(err).NotTo(HaveOccurred())
1092-
})
1093-
1094-
It("should not reconfigure the database", func() {
1095-
Expect(adminClient.DatabaseConfiguration.LogVersion).To(Equal(3))
1096-
})
1097-
})
1098-
1099-
Context("with changes disabled", func() {
1100-
BeforeEach(func() {
1101-
shouldCompleteReconciliation = false
1102-
cluster.Spec.AutomationOptions.ConfigureDatabase = pointer.Bool(false)
1103-
cluster.Spec.DatabaseConfiguration.RedundancyMode = fdbv1beta2.RedundancyModeTriple
1104-
1105-
err = k8sClient.Update(context.TODO(), cluster)
1106-
Expect(err).NotTo(HaveOccurred())
1107-
})
1108-
1109-
JustBeforeEach(func() {
1110-
generations, err := reloadClusterGenerations(cluster)
1111-
Expect(err).NotTo(HaveOccurred())
1112-
Expect(generations).To(Equal(fdbv1beta2.ClusterGenerationStatus{
1113-
Reconciled: originalVersion,
1114-
NeedsConfigurationChange: originalVersion + 1,
1115-
}))
1116-
})
1117-
1118-
It("should not change the database configuration", func() {
1119-
adminClient, err := mock.NewMockAdminClientUncast(cluster, k8sClient)
1120-
Expect(err).NotTo(HaveOccurred())
1121-
Expect(adminClient.DatabaseConfiguration.RedundancyMode).To(Equal(fdbv1beta2.RedundancyModeDouble))
1122-
})
1123-
})
1124-
})
1125-
11261036
Context("with a change to pod labels", func() {
11271037
BeforeEach(func() {
11281038
cluster.Spec.Processes = map[fdbv1beta2.ProcessClass]fdbv1beta2.ProcessSettings{fdbv1beta2.ProcessClassGeneral: {PodTemplate: &corev1.PodTemplateSpec{

controllers/exclude_processes.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,9 @@ func (e excludeProcesses) reconcile(ctx context.Context, r *FoundationDBClusterR
7474
}
7575

7676
// Make sure the exclusions are coordinated across multiple operator instances.
77-
if cluster.ShouldUseLocks() {
78-
err = r.takeLock(logger, cluster, "exclude processes")
79-
if err != nil {
80-
return &requeue{curError: err, delayedRequeue: true}
81-
}
77+
err = r.takeLock(logger, cluster, "exclude processes")
78+
if err != nil {
79+
return &requeue{curError: err, delayedRequeue: true}
8280
}
8381

8482
// We need the information below to check if the excluded processes are coordinators to make sure we can change the

controllers/remove_process_groups.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -279,11 +279,9 @@ func includeProcessGroup(ctx context.Context, logger logr.Logger, r *FoundationD
279279
}
280280

281281
// Make sure the inclusion are coordinated across multiple operator instances.
282-
if cluster.ShouldUseLocks() {
283-
err = r.takeLock(logger, cluster, "remove process groups")
284-
if err != nil {
285-
return err
286-
}
282+
err = r.takeLock(logger, cluster, "remove process groups")
283+
if err != nil {
284+
return err
287285
}
288286

289287
// Make sure it's safe to include processes.

controllers/update_database_configuration.go

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,12 @@ import (
2525
"fmt"
2626
"time"
2727

28+
fdbv1beta2 "github.com/FoundationDB/fdb-kubernetes-operator/v2/api/v1beta2"
2829
"github.com/FoundationDB/fdb-kubernetes-operator/v2/pkg/fdbstatus"
29-
3030
"github.com/go-logr/logr"
31-
32-
"k8s.io/utils/pointer"
33-
34-
fdbv1beta2 "github.com/FoundationDB/fdb-kubernetes-operator/v2/api/v1beta2"
3531
corev1 "k8s.io/api/core/v1"
3632
"k8s.io/apimachinery/pkg/api/equality"
33+
"k8s.io/utils/pointer"
3734
)
3835

3936
// updateDatabaseConfiguration provides a reconciliation step for changing the
@@ -62,42 +59,38 @@ func (u updateDatabaseConfiguration) reconcile(_ context.Context, r *FoundationD
6259
}
6360
}
6461

65-
initialConfig := !cluster.Status.Configured
66-
if !initialConfig && !status.Client.DatabaseStatus.Available {
67-
logger.Info("Skipping database configuration change because database is unavailable")
68-
return &requeue{message: "cluster is not available", delayedRequeue: true, delay: 5 * time.Second}
69-
}
70-
62+
clusterIsConfigured := fdbstatus.ClusterIsConfigured(cluster, status)
7163
desiredConfiguration := cluster.DesiredDatabaseConfiguration()
72-
desiredConfiguration.RoleCounts.Storage = 0
7364
currentConfiguration := status.Cluster.DatabaseConfiguration.NormalizeConfiguration(cluster)
7465

75-
runningVersion, err := fdbv1beta2.ParseFdbVersion(cluster.GetRunningVersion())
76-
if err != nil {
77-
return &requeue{curError: err, delayedRequeue: true}
78-
}
79-
80-
if initialConfig || !equality.Semantic.DeepEqual(desiredConfiguration, currentConfiguration) {
66+
if !clusterIsConfigured || !equality.Semantic.DeepEqual(desiredConfiguration, currentConfiguration) {
8167
var nextConfiguration fdbv1beta2.DatabaseConfiguration
82-
if initialConfig {
83-
nextConfiguration = desiredConfiguration
84-
} else {
68+
if clusterIsConfigured {
8569
nextConfiguration = currentConfiguration.GetNextConfigurationChange(desiredConfiguration)
70+
} else {
71+
nextConfiguration = desiredConfiguration
72+
}
73+
configurationString, configErr := nextConfiguration.GetConfigurationString()
74+
if configErr != nil {
75+
return &requeue{curError: err, delayedRequeue: true}
8676
}
87-
configurationString, _ := nextConfiguration.GetConfigurationString()
8877

89-
if !initialConfig {
78+
// If the cluster is configured run additional safety checks before performing the database configuration change.
79+
if clusterIsConfigured {
80+
runningVersion, err := fdbv1beta2.ParseFdbVersion(cluster.GetRunningVersion())
81+
if err != nil {
82+
return &requeue{curError: err, delayedRequeue: true}
83+
}
84+
9085
err = fdbstatus.ConfigurationChangeAllowed(status, runningVersion.SupportsRecoveryState() && r.EnableRecoveryState)
9186
if err != nil {
9287
logger.Info("Changing current configuration is not safe", "error", err, "current configuration", currentConfiguration, "desired configuration", desiredConfiguration)
9388
r.Recorder.Event(cluster, corev1.EventTypeNormal, "NeedsConfigurationChange",
94-
fmt.Sprintf("Spec require configuration change to `%s`, but configuration change is not safe: %s", configurationString, err.Error()))
95-
return &requeue{message: "Configuration change is not safe, retry later", delayedRequeue: true, delay: 10 * time.Second}
89+
fmt.Sprintf("Spec requires configuration change to `%s`, but configuration change is not safe: %s", configurationString, err.Error()))
90+
return &requeue{message: fmt.Sprintf("Configuration change is not safe: %s, will retry", err.Error()), delayedRequeue: true, delay: 10 * time.Second}
9691
}
97-
}
9892

99-
if !initialConfig {
100-
err := r.takeLock(logger, cluster,
93+
err = r.takeLock(logger, cluster,
10194
fmt.Sprintf("reconfiguring the database to `%s`", configurationString))
10295
if err != nil {
10396
return &requeue{curError: err, delayedRequeue: true}
@@ -108,18 +101,14 @@ func (u updateDatabaseConfiguration) reconcile(_ context.Context, r *FoundationD
108101
r.Recorder.Event(cluster, corev1.EventTypeNormal, "ConfiguringDatabase",
109102
fmt.Sprintf("Setting database configuration to `%s`", configurationString),
110103
)
111-
err = adminClient.ConfigureDatabase(nextConfiguration, initialConfig)
104+
err = adminClient.ConfigureDatabase(nextConfiguration, !clusterIsConfigured)
112105
if err != nil {
113106
return &requeue{curError: err, delayedRequeue: true}
114107
}
115108

116-
if initialConfig {
117-
return &requeue{message: "Requeuing for fetching the initial configuration from FDB cluster", delay: 1 * time.Second}
118-
}
119-
120-
logger.Info("Configured database", "initialConfig", initialConfig)
109+
logger.Info("Configured database", "clusterIsConfigured", clusterIsConfigured)
121110
if !equality.Semantic.DeepEqual(nextConfiguration, desiredConfiguration) {
122-
return &requeue{message: "Requeuing for next stage of database configuration change", delayedRequeue: true}
111+
return &requeue{message: "Requeuing for next stage of database configuration change", delay: 30 * time.Second, delayedRequeue: true}
123112
}
124113
}
125114

0 commit comments

Comments
 (0)