From 5532b11e7281a2a34111a7a051d1418c0112cc30 Mon Sep 17 00:00:00 2001 From: Johannes Scheuermann Date: Mon, 28 Mar 2022 18:41:32 +0100 Subject: [PATCH] Fix role counts for versions prior to 7.0 (#1142) * Fix role counts for versions prior to 7.0 --- .../foundationdb_database_configuration.go | 16 +- api/v1beta2/foundationdbcluster_types.go | 6 +- api/v1beta2/foundationdbcluster_types_test.go | 1156 +++++++++++------ controllers/admin_client_mock.go | 13 +- controllers/admin_client_test.go | 141 +- controllers/cluster_controller_test.go | 19 +- 6 files changed, 934 insertions(+), 417 deletions(-) diff --git a/api/v1beta2/foundationdb_database_configuration.go b/api/v1beta2/foundationdb_database_configuration.go index 5e168f3fd..d9a3d78e4 100644 --- a/api/v1beta2/foundationdb_database_configuration.go +++ b/api/v1beta2/foundationdb_database_configuration.go @@ -236,7 +236,7 @@ func (configuration DatabaseConfiguration) getRegion(id string, priority int) Re // The default LogRouters value will be equal to 3 times the Logs value when // the UsableRegions is greater than 1. It will be equal to -1 when the // UsableRegions is less than or equal to 1. -func (configuration *DatabaseConfiguration) GetRoleCountsWithDefaults(faultTolerance int) RoleCounts { +func (configuration *DatabaseConfiguration) GetRoleCountsWithDefaults(version Version, faultTolerance int) RoleCounts { counts := configuration.RoleCounts.DeepCopy() if counts.Storage == 0 { counts.Storage = 2*faultTolerance + 1 @@ -247,11 +247,13 @@ func (configuration *DatabaseConfiguration) GetRoleCountsWithDefaults(faultToler if counts.Proxies == 0 { counts.Proxies = 3 } - if counts.CommitProxies == 0 { - counts.CommitProxies = 2 - } - if counts.GrvProxies == 0 { - counts.GrvProxies = 1 + if version.HasSeparatedProxies() { + if counts.CommitProxies == 0 { + counts.CommitProxies = 2 + } + if counts.GrvProxies == 0 { + counts.GrvProxies = 1 + } } if counts.Resolvers == 0 { counts.Resolvers = 1 @@ -528,7 +530,7 @@ func (configuration DatabaseConfiguration) AreSeparatedProxiesConfigured() bool // "proxies=%d" using the correct counts of the configuration object. // func (configuration DatabaseConfiguration) GetProxiesString(version Version) string { - counts := configuration.GetRoleCountsWithDefaults(DesiredFaultTolerance(configuration.RedundancyMode)) + counts := configuration.GetRoleCountsWithDefaults(version, DesiredFaultTolerance(configuration.RedundancyMode)) if version.HasSeparatedProxies() && configuration.AreSeparatedProxiesConfigured() { return fmt.Sprintf(" commit_proxies=%d grv_proxies=%d", counts.CommitProxies, counts.GrvProxies) } diff --git a/api/v1beta2/foundationdbcluster_types.go b/api/v1beta2/foundationdbcluster_types.go index 37ba33274..96b2340cd 100644 --- a/api/v1beta2/foundationdbcluster_types.go +++ b/api/v1beta2/foundationdbcluster_types.go @@ -943,7 +943,9 @@ func (cluster *FoundationDBCluster) GetProcessSettings(processClass ProcessClass // the UsableRegions is greater than 1. It will be equal to -1 when the // UsableRegions is less than or equal to 1. func (cluster *FoundationDBCluster) GetRoleCountsWithDefaults() RoleCounts { - return cluster.Spec.DatabaseConfiguration.GetRoleCountsWithDefaults(cluster.DesiredFaultTolerance()) + // We can ignore the error here since the version will be validated in an earlier step. + version, _ := ParseFdbVersion(cluster.Spec.Version) + return cluster.Spec.DatabaseConfiguration.GetRoleCountsWithDefaults(version, cluster.DesiredFaultTolerance()) } // calculateProcessCount determines the process count from a given role count. @@ -1158,7 +1160,7 @@ func (cluster *FoundationDBCluster) CheckReconciliation(log logr.Logger) (bool, desiredConfiguration := cluster.DesiredDatabaseConfiguration() if !equality.Semantic.DeepEqual(cluster.Status.DatabaseConfiguration, desiredConfiguration) { - logger.Info("Pending database configuration change", "state", "NeedsConfigurationChange") + logger.Info("Pending database configuration change", "state", "NeedsConfigurationChange", "current", cluster.Status.DatabaseConfiguration, "desired", desiredConfiguration) cluster.Status.Generations.NeedsConfigurationChange = cluster.ObjectMeta.Generation reconciled = false } diff --git a/api/v1beta2/foundationdbcluster_types_test.go b/api/v1beta2/foundationdbcluster_types_test.go index a355006c6..90a9851ae 100644 --- a/api/v1beta2/foundationdbcluster_types_test.go +++ b/api/v1beta2/foundationdbcluster_types_test.go @@ -41,110 +41,212 @@ var _ = Describe("[api] FoundationDBCluster", func() { log := logf.Log.WithName("controller") When("getting the default role counts", func() { - It("should return the default role counts", func() { - cluster := &FoundationDBCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "default", - }, - Spec: FoundationDBClusterSpec{ - DatabaseConfiguration: DatabaseConfiguration{ - RedundancyMode: RedundancyModeDouble, + When("the version does not supports grv and commit proxies", func() { + It("should return the default role counts", func() { + cluster := &FoundationDBCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "default", }, - }, - } + Spec: FoundationDBClusterSpec{ + DatabaseConfiguration: DatabaseConfiguration{ + RedundancyMode: RedundancyModeDouble, + }, + Version: "6.3.24", + }, + } - counts := cluster.GetRoleCountsWithDefaults() - Expect(counts).To(Equal(RoleCounts{ - Storage: 3, - Logs: 3, - Proxies: 3, - CommitProxies: 2, - GrvProxies: 1, - Resolvers: 1, - RemoteLogs: -1, - LogRouters: -1, - })) - Expect(counts.Map()).To(Equal(map[ProcessClass]int{ - "logs": 3, - "proxies": 3, - "resolvers": 1, - "remote_logs": -1, - "log_routers": -1, - "commit_proxies": 2, - "grv_proxies": 1, - })) - Expect(cluster.Spec.DatabaseConfiguration.RoleCounts).To(Equal(RoleCounts{})) + counts := cluster.GetRoleCountsWithDefaults() + Expect(counts).To(Equal(RoleCounts{ + Storage: 3, + Logs: 3, + Proxies: 3, + Resolvers: 1, + RemoteLogs: -1, + LogRouters: -1, + })) + Expect(counts.Map()).To(Equal(map[ProcessClass]int{ + "logs": 3, + "proxies": 3, + "resolvers": 1, + "commit_proxies": 0, + "grv_proxies": 0, + "remote_logs": -1, + "log_routers": -1, + })) + Expect(cluster.Spec.DatabaseConfiguration.RoleCounts).To(Equal(RoleCounts{})) + + cluster.Spec.DatabaseConfiguration.UsableRegions = 2 + counts = cluster.GetRoleCountsWithDefaults() + Expect(counts).To(Equal(RoleCounts{ + Storage: 3, + Logs: 3, + Proxies: 3, + Resolvers: 1, + RemoteLogs: 3, + LogRouters: 3, + })) + Expect(counts.Map()).To(Equal(map[ProcessClass]int{ + "logs": 3, + "proxies": 3, + "commit_proxies": 0, + "grv_proxies": 0, + "resolvers": 1, + "remote_logs": 3, + "log_routers": 3, + })) - cluster.Spec.DatabaseConfiguration.UsableRegions = 2 - counts = cluster.GetRoleCountsWithDefaults() - Expect(counts).To(Equal(RoleCounts{ - Storage: 3, - Logs: 3, - CommitProxies: 2, - GrvProxies: 1, - Proxies: 3, - Resolvers: 1, - RemoteLogs: 3, - LogRouters: 3, - })) - Expect(counts.Map()).To(Equal(map[ProcessClass]int{ - "logs": 3, - "proxies": 3, - "resolvers": 1, - "remote_logs": 3, - "log_routers": 3, - "commit_proxies": 2, - "grv_proxies": 1, - })) + cluster.Spec.DatabaseConfiguration.RoleCounts = RoleCounts{ + Storage: 5, + } - cluster.Spec.DatabaseConfiguration.RoleCounts = RoleCounts{ - Storage: 5, - } + counts = cluster.GetRoleCountsWithDefaults() + Expect(counts).To(Equal(RoleCounts{ + Storage: 5, + Logs: 3, + Proxies: 3, + Resolvers: 1, + RemoteLogs: 3, + LogRouters: 3, + })) - counts = cluster.GetRoleCountsWithDefaults() - Expect(counts).To(Equal(RoleCounts{ - Storage: 5, - Logs: 3, - Proxies: 3, - GrvProxies: 1, - CommitProxies: 2, - Resolvers: 1, - RemoteLogs: 3, - LogRouters: 3, - })) + cluster.Spec.DatabaseConfiguration.RoleCounts = RoleCounts{ + Logs: 8, + } + counts = cluster.GetRoleCountsWithDefaults() + Expect(counts).To(Equal(RoleCounts{ + Storage: 3, + Logs: 8, + Proxies: 3, + Resolvers: 1, + RemoteLogs: 8, + LogRouters: 8, + })) - cluster.Spec.DatabaseConfiguration.RoleCounts = RoleCounts{ - Logs: 8, - } - counts = cluster.GetRoleCountsWithDefaults() - Expect(counts).To(Equal(RoleCounts{ - Storage: 3, - Logs: 8, - CommitProxies: 2, - GrvProxies: 1, - Proxies: 3, - Resolvers: 1, - RemoteLogs: 8, - LogRouters: 8, - })) + cluster.Spec.DatabaseConfiguration.RoleCounts = RoleCounts{ + Logs: 4, + RemoteLogs: 5, + LogRouters: 6, + } + counts = cluster.GetRoleCountsWithDefaults() + Expect(counts).To(Equal(RoleCounts{ + Storage: 3, + Logs: 4, + Proxies: 3, + Resolvers: 1, + RemoteLogs: 5, + LogRouters: 6, + })) + }) + }) - cluster.Spec.DatabaseConfiguration.RoleCounts = RoleCounts{ - Logs: 4, - RemoteLogs: 5, - LogRouters: 6, - } - counts = cluster.GetRoleCountsWithDefaults() - Expect(counts).To(Equal(RoleCounts{ - Storage: 3, - Logs: 4, - Proxies: 3, - GrvProxies: 1, - CommitProxies: 2, - Resolvers: 1, - RemoteLogs: 5, - LogRouters: 6, - })) + When("the version supports grv and commit proxies", func() { + It("should return the default role counts", func() { + cluster := &FoundationDBCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "default", + }, + Spec: FoundationDBClusterSpec{ + DatabaseConfiguration: DatabaseConfiguration{ + RedundancyMode: RedundancyModeDouble, + }, + Version: "7.0.0", + }, + } + + counts := cluster.GetRoleCountsWithDefaults() + Expect(counts).To(Equal(RoleCounts{ + Storage: 3, + Logs: 3, + Proxies: 3, + CommitProxies: 2, + GrvProxies: 1, + Resolvers: 1, + RemoteLogs: -1, + LogRouters: -1, + })) + Expect(counts.Map()).To(Equal(map[ProcessClass]int{ + "logs": 3, + "proxies": 3, + "resolvers": 1, + "remote_logs": -1, + "log_routers": -1, + "commit_proxies": 2, + "grv_proxies": 1, + })) + Expect(cluster.Spec.DatabaseConfiguration.RoleCounts).To(Equal(RoleCounts{})) + + cluster.Spec.DatabaseConfiguration.UsableRegions = 2 + counts = cluster.GetRoleCountsWithDefaults() + Expect(counts).To(Equal(RoleCounts{ + Storage: 3, + Logs: 3, + CommitProxies: 2, + GrvProxies: 1, + Proxies: 3, + Resolvers: 1, + RemoteLogs: 3, + LogRouters: 3, + })) + Expect(counts.Map()).To(Equal(map[ProcessClass]int{ + "logs": 3, + "proxies": 3, + "resolvers": 1, + "remote_logs": 3, + "log_routers": 3, + "commit_proxies": 2, + "grv_proxies": 1, + })) + + cluster.Spec.DatabaseConfiguration.RoleCounts = RoleCounts{ + Storage: 5, + } + + counts = cluster.GetRoleCountsWithDefaults() + Expect(counts).To(Equal(RoleCounts{ + Storage: 5, + Logs: 3, + Proxies: 3, + GrvProxies: 1, + CommitProxies: 2, + Resolvers: 1, + RemoteLogs: 3, + LogRouters: 3, + })) + + cluster.Spec.DatabaseConfiguration.RoleCounts = RoleCounts{ + Logs: 8, + } + counts = cluster.GetRoleCountsWithDefaults() + Expect(counts).To(Equal(RoleCounts{ + Storage: 3, + Logs: 8, + CommitProxies: 2, + GrvProxies: 1, + Proxies: 3, + Resolvers: 1, + RemoteLogs: 8, + LogRouters: 8, + })) + + cluster.Spec.DatabaseConfiguration.RoleCounts = RoleCounts{ + Logs: 4, + RemoteLogs: 5, + LogRouters: 6, + } + counts = cluster.GetRoleCountsWithDefaults() + Expect(counts).To(Equal(RoleCounts{ + Storage: 3, + Logs: 4, + Proxies: 3, + GrvProxies: 1, + CommitProxies: 2, + Resolvers: 1, + RemoteLogs: 5, + LogRouters: 6, + })) + }) }) }) @@ -567,56 +669,122 @@ var _ = Describe("[api] FoundationDBCluster", func() { }) When("getting the cluster database configuration", func() { - It("should be parsed correctly", func() { - cluster := &FoundationDBCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "default", - }, - Spec: FoundationDBClusterSpec{ - DatabaseConfiguration: DatabaseConfiguration{ - RedundancyMode: RedundancyModeDouble, - StorageEngine: "ssd", - RoleCounts: RoleCounts{ - Storage: 5, - Logs: 4, - Proxies: 5, + var cluster *FoundationDBCluster + + When("the version supports grv and commit proxies", func() { + BeforeEach(func() { + cluster = &FoundationDBCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "default", + }, + Spec: FoundationDBClusterSpec{ + DatabaseConfiguration: DatabaseConfiguration{ + RedundancyMode: RedundancyModeDouble, + StorageEngine: "ssd", + RoleCounts: RoleCounts{ + Storage: 5, + Logs: 4, + Proxies: 5, + }, }, + Version: "7.0.0", }, - }, - } + } + }) - Expect(cluster.DesiredDatabaseConfiguration()).To(Equal(DatabaseConfiguration{ - RedundancyMode: RedundancyModeDouble, - StorageEngine: "ssd-2", - UsableRegions: 1, - RoleCounts: RoleCounts{ - Logs: 4, - Proxies: 5, - CommitProxies: 2, - GrvProxies: 1, - Resolvers: 1, - LogRouters: -1, - RemoteLogs: -1, - }, - })) + It("should be parsed correctly", func() { + Expect(cluster.DesiredDatabaseConfiguration()).To(Equal(DatabaseConfiguration{ + RedundancyMode: RedundancyModeDouble, + StorageEngine: "ssd-2", + UsableRegions: 1, + RoleCounts: RoleCounts{ + Logs: 4, + Proxies: 5, + CommitProxies: 2, + GrvProxies: 1, + Resolvers: 1, + LogRouters: -1, + RemoteLogs: -1, + }, + })) - cluster.Spec = FoundationDBClusterSpec{} + cluster.Spec = FoundationDBClusterSpec{ + Version: "7.0.0", + } - Expect(cluster.DesiredDatabaseConfiguration()).To(Equal(DatabaseConfiguration{ - RedundancyMode: RedundancyModeDouble, - StorageEngine: "ssd-2", - UsableRegions: 1, - RoleCounts: RoleCounts{ - Logs: 3, - Proxies: 3, - CommitProxies: 2, - GrvProxies: 1, - Resolvers: 1, - LogRouters: -1, - RemoteLogs: -1, - }, - })) + Expect(cluster.DesiredDatabaseConfiguration()).To(Equal(DatabaseConfiguration{ + RedundancyMode: RedundancyModeDouble, + StorageEngine: "ssd-2", + UsableRegions: 1, + RoleCounts: RoleCounts{ + Logs: 3, + Proxies: 3, + CommitProxies: 2, + GrvProxies: 1, + Resolvers: 1, + LogRouters: -1, + RemoteLogs: -1, + }, + })) + }) + }) + + When("the version supports grv and commit proxies", func() { + BeforeEach(func() { + cluster = &FoundationDBCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "default", + }, + Spec: FoundationDBClusterSpec{ + DatabaseConfiguration: DatabaseConfiguration{ + RedundancyMode: RedundancyModeDouble, + StorageEngine: "ssd", + RoleCounts: RoleCounts{ + Storage: 5, + Logs: 4, + Proxies: 5, + }, + }, + Version: "6.3.23", + }, + } + }) + + It("should be parsed correctly", func() { + Expect(cluster.DesiredDatabaseConfiguration()).To(Equal(DatabaseConfiguration{ + RedundancyMode: RedundancyModeDouble, + StorageEngine: "ssd-2", + UsableRegions: 1, + RoleCounts: RoleCounts{ + Logs: 4, + Proxies: 5, + CommitProxies: 0, + GrvProxies: 0, + Resolvers: 1, + LogRouters: -1, + RemoteLogs: -1, + }, + })) + + cluster.Spec = FoundationDBClusterSpec{} + + Expect(cluster.DesiredDatabaseConfiguration()).To(Equal(DatabaseConfiguration{ + RedundancyMode: RedundancyModeDouble, + StorageEngine: "ssd-2", + UsableRegions: 1, + RoleCounts: RoleCounts{ + Logs: 3, + Proxies: 3, + CommitProxies: 0, + GrvProxies: 0, + Resolvers: 1, + LogRouters: -1, + RemoteLogs: -1, + }, + })) + }) }) }) @@ -2509,252 +2677,510 @@ var _ = Describe("[api] FoundationDBCluster", func() { }) When("checking the reconciliation for a cluster", func() { - It("should return the correct status", func() { - createCluster := func() *FoundationDBCluster { - return &FoundationDBCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "sample-cluster", - Namespace: "default", - Generation: 2, - }, - Spec: FoundationDBClusterSpec{ - Version: Versions.Default.String(), - DatabaseConfiguration: DatabaseConfiguration{}, - }, - Status: FoundationDBClusterStatus{ - Health: ClusterHealth{ - Available: true, - Healthy: true, + var createCluster func() *FoundationDBCluster + + When("the cluster supports grv and commit proxies", func() { + BeforeEach(func() { + createCluster = func() *FoundationDBCluster { + return &FoundationDBCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sample-cluster", + Namespace: "default", + Generation: 2, }, - RequiredAddresses: RequiredAddressSet{ - NonTLS: true, + Spec: FoundationDBClusterSpec{ + Version: "7.0.0", + DatabaseConfiguration: DatabaseConfiguration{}, + }, + Status: FoundationDBClusterStatus{ + Health: ClusterHealth{ + Available: true, + Healthy: true, + }, + RequiredAddresses: RequiredAddressSet{ + NonTLS: true, + }, + DatabaseConfiguration: DatabaseConfiguration{ + RedundancyMode: RedundancyModeDouble, + StorageEngine: "ssd-2", + UsableRegions: 1, + RoleCounts: RoleCounts{ + Logs: 3, + Proxies: 3, + GrvProxies: 1, + CommitProxies: 2, + Resolvers: 1, + LogRouters: -1, + RemoteLogs: -1, + }, + }, + Generations: ClusterGenerationStatus{ + Reconciled: 1, + }, + ProcessGroups: []*ProcessGroupStatus{ + {ProcessGroupID: "storage-1", ProcessClass: "storage"}, + {ProcessGroupID: "storage-2", ProcessClass: "storage"}, + {ProcessGroupID: "storage-3", ProcessClass: "storage"}, + {ProcessGroupID: "stateless-1", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-2", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-3", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-4", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-5", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-6", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-7", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-8", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-9", ProcessClass: "stateless"}, + {ProcessGroupID: "log-1", ProcessClass: "log"}, + {ProcessGroupID: "log-2", ProcessClass: "log"}, + {ProcessGroupID: "log-3", ProcessClass: "log"}, + {ProcessGroupID: "log-4", ProcessClass: "log"}, + }, + Configured: true, + }, + } + } + }) + + It("should return the correct status", func() { + cluster := createCluster() + + result, err := cluster.CheckReconciliation(log) + Expect(result).To(BeTrue()) + Expect(err).NotTo(HaveOccurred()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 2, + })) + + cluster = createCluster() + cluster.Status.Configured = false + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsConfigurationChange: 2, + })) + + cluster = createCluster() + cluster.Status.ProcessGroups = append(cluster.Status.ProcessGroups, &ProcessGroupStatus{ProcessGroupID: "storage-5", ProcessClass: "storage"}) + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsShrink: 2, + })) + + cluster = createCluster() + cluster.Status.ProcessGroups = cluster.Status.ProcessGroups[1:] + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsGrow: 2, + })) + + cluster = createCluster() + cluster.Status.Health.Available = false + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + DatabaseUnavailable: 2, + })) + + cluster = createCluster() + cluster.Spec.DatabaseConfiguration.StorageEngine = "ssd-1" + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsConfigurationChange: 2, + })) + + cluster = createCluster() + cluster.Status.HasIncorrectConfigMap = true + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsMonitorConfUpdate: 2, + })) + + cluster = createCluster() + cluster.Status.RequiredAddresses.TLS = true + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + HasExtraListeners: 2, + })) + + cluster = createCluster() + cluster.Spec.ProcessCounts.Storage = 2 + cluster.Status.ProcessGroups[0].MarkForRemoval() + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsShrink: 2, + })) + + cluster = createCluster() + cluster.Spec.ProcessCounts.Storage = 2 + cluster.Status.ProcessGroups[0].MarkForRemoval() + cluster.Status.ProcessGroups[0].UpdateCondition(ResourcesTerminating, true, nil, "") + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeTrue()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 2, + HasPendingRemoval: 2, + })) + + cluster = createCluster() + cluster.Spec.ProcessCounts.Storage = 2 + cluster.Status.ProcessGroups[0].MarkForRemoval() + cluster.Status.ProcessGroups[0].SetExclude() + cluster.Status.ProcessGroups[0].UpdateCondition(IncorrectCommandLine, true, nil, "") + cluster.Status.ProcessGroups[0].UpdateCondition(ResourcesTerminating, true, nil, "") + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeTrue()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 2, + HasPendingRemoval: 2, + })) + + cluster = createCluster() + cluster.Status.HasIncorrectServiceConfig = true + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsServiceUpdate: 2, + })) + + cluster = createCluster() + cluster.Status.NeedsNewCoordinators = true + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsCoordinatorChange: 2, + })) + + cluster = createCluster() + cluster.Status.ProcessGroups[0].UpdateCondition(IncorrectCommandLine, true, nil, "") + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + HasUnhealthyProcess: 2, + })) + + cluster = createCluster() + cluster.Spec.LockOptions.DenyList = append(cluster.Spec.LockOptions.DenyList, LockDenyListEntry{ID: "dc1"}) + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsLockConfigurationChanges: 2, + })) + + cluster = createCluster() + cluster.Spec.LockOptions.DenyList = append(cluster.Spec.LockOptions.DenyList, LockDenyListEntry{ID: "dc1"}) + cluster.Status.Locks.DenyList = []string{"dc1", "dc2"} + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeTrue()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 2, + })) + + cluster = createCluster() + cluster.Spec.LockOptions.DenyList = append(cluster.Spec.LockOptions.DenyList, LockDenyListEntry{ID: "dc1", Allow: true}) + cluster.Status.Locks.DenyList = []string{"dc1", "dc2"} + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsLockConfigurationChanges: 2, + })) + + cluster = createCluster() + cluster.Spec.LockOptions.DenyList = append(cluster.Spec.LockOptions.DenyList, LockDenyListEntry{ID: "dc1", Allow: true}) + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeTrue()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 2, + })) + }) + }) + + When("the cluster does not support grv and commit proxies", func() { + BeforeEach(func() { + createCluster = func() *FoundationDBCluster { + return &FoundationDBCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sample-cluster", + Namespace: "default", + Generation: 2, }, - DatabaseConfiguration: DatabaseConfiguration{ - RedundancyMode: RedundancyModeDouble, - StorageEngine: "ssd-2", - UsableRegions: 1, - RoleCounts: RoleCounts{ - Logs: 3, - Proxies: 3, - GrvProxies: 1, - CommitProxies: 2, - Resolvers: 1, - LogRouters: -1, - RemoteLogs: -1, - }, - }, - Generations: ClusterGenerationStatus{ - Reconciled: 1, - }, - ProcessGroups: []*ProcessGroupStatus{ - {ProcessGroupID: "storage-1", ProcessClass: "storage"}, - {ProcessGroupID: "storage-2", ProcessClass: "storage"}, - {ProcessGroupID: "storage-3", ProcessClass: "storage"}, - {ProcessGroupID: "stateless-1", ProcessClass: "stateless"}, - {ProcessGroupID: "stateless-2", ProcessClass: "stateless"}, - {ProcessGroupID: "stateless-3", ProcessClass: "stateless"}, - {ProcessGroupID: "stateless-4", ProcessClass: "stateless"}, - {ProcessGroupID: "stateless-5", ProcessClass: "stateless"}, - {ProcessGroupID: "stateless-6", ProcessClass: "stateless"}, - {ProcessGroupID: "stateless-7", ProcessClass: "stateless"}, - {ProcessGroupID: "stateless-8", ProcessClass: "stateless"}, - {ProcessGroupID: "stateless-9", ProcessClass: "stateless"}, - {ProcessGroupID: "log-1", ProcessClass: "log"}, - {ProcessGroupID: "log-2", ProcessClass: "log"}, - {ProcessGroupID: "log-3", ProcessClass: "log"}, - {ProcessGroupID: "log-4", ProcessClass: "log"}, - }, - Configured: true, - }, + Spec: FoundationDBClusterSpec{ + Version: Versions.Default.String(), + DatabaseConfiguration: DatabaseConfiguration{}, + }, + Status: FoundationDBClusterStatus{ + Health: ClusterHealth{ + Available: true, + Healthy: true, + }, + RequiredAddresses: RequiredAddressSet{ + NonTLS: true, + }, + DatabaseConfiguration: DatabaseConfiguration{ + RedundancyMode: RedundancyModeDouble, + StorageEngine: "ssd-2", + UsableRegions: 1, + RoleCounts: RoleCounts{ + Logs: 3, + Proxies: 3, + GrvProxies: 0, + CommitProxies: 0, + Resolvers: 1, + LogRouters: -1, + RemoteLogs: -1, + }, + }, + Generations: ClusterGenerationStatus{ + Reconciled: 1, + }, + ProcessGroups: []*ProcessGroupStatus{ + {ProcessGroupID: "storage-1", ProcessClass: "storage"}, + {ProcessGroupID: "storage-2", ProcessClass: "storage"}, + {ProcessGroupID: "storage-3", ProcessClass: "storage"}, + {ProcessGroupID: "stateless-1", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-2", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-3", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-4", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-5", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-6", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-7", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-8", ProcessClass: "stateless"}, + {ProcessGroupID: "stateless-9", ProcessClass: "stateless"}, + {ProcessGroupID: "log-1", ProcessClass: "log"}, + {ProcessGroupID: "log-2", ProcessClass: "log"}, + {ProcessGroupID: "log-3", ProcessClass: "log"}, + {ProcessGroupID: "log-4", ProcessClass: "log"}, + }, + Configured: true, + }, + } } - } + }) - cluster := createCluster() + It("should return the correct status", func() { + cluster := createCluster() - result, err := cluster.CheckReconciliation(log) - Expect(result).To(BeTrue()) - Expect(err).NotTo(HaveOccurred()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 2, - })) + result, err := cluster.CheckReconciliation(log) + Expect(result).To(BeTrue()) + Expect(err).NotTo(HaveOccurred()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 2, + })) - cluster = createCluster() - cluster.Status.Configured = false - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeFalse()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 1, - NeedsConfigurationChange: 2, - })) + cluster = createCluster() + cluster.Status.Configured = false + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsConfigurationChange: 2, + })) - cluster = createCluster() - cluster.Status.ProcessGroups = append(cluster.Status.ProcessGroups, &ProcessGroupStatus{ProcessGroupID: "storage-5", ProcessClass: "storage"}) - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeFalse()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 1, - NeedsShrink: 2, - })) + cluster = createCluster() + cluster.Status.ProcessGroups = append(cluster.Status.ProcessGroups, &ProcessGroupStatus{ProcessGroupID: "storage-5", ProcessClass: "storage"}) + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsShrink: 2, + })) - cluster = createCluster() - cluster.Status.ProcessGroups = cluster.Status.ProcessGroups[1:] - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeFalse()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 1, - NeedsGrow: 2, - })) + cluster = createCluster() + cluster.Status.ProcessGroups = cluster.Status.ProcessGroups[1:] + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsGrow: 2, + })) - cluster = createCluster() - cluster.Status.Health.Available = false - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeFalse()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 1, - DatabaseUnavailable: 2, - })) + cluster = createCluster() + cluster.Status.Health.Available = false + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + DatabaseUnavailable: 2, + })) - cluster = createCluster() - cluster.Spec.DatabaseConfiguration.StorageEngine = "ssd-1" - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeFalse()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 1, - NeedsConfigurationChange: 2, - })) + cluster = createCluster() + cluster.Spec.DatabaseConfiguration.StorageEngine = "ssd-1" + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsConfigurationChange: 2, + })) - cluster = createCluster() - cluster.Status.HasIncorrectConfigMap = true - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeFalse()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 1, - NeedsMonitorConfUpdate: 2, - })) + cluster = createCluster() + cluster.Status.HasIncorrectConfigMap = true + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsMonitorConfUpdate: 2, + })) - cluster = createCluster() - cluster.Status.RequiredAddresses.TLS = true - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeFalse()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 1, - HasExtraListeners: 2, - })) + cluster = createCluster() + cluster.Status.RequiredAddresses.TLS = true + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + HasExtraListeners: 2, + })) - cluster = createCluster() - cluster.Spec.ProcessCounts.Storage = 2 - cluster.Status.ProcessGroups[0].MarkForRemoval() - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeFalse()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 1, - NeedsShrink: 2, - })) + cluster = createCluster() + cluster.Spec.ProcessCounts.Storage = 2 + cluster.Status.ProcessGroups[0].MarkForRemoval() + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsShrink: 2, + })) - cluster = createCluster() - cluster.Spec.ProcessCounts.Storage = 2 - cluster.Status.ProcessGroups[0].MarkForRemoval() - cluster.Status.ProcessGroups[0].UpdateCondition(ResourcesTerminating, true, nil, "") - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeTrue()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 2, - HasPendingRemoval: 2, - })) + cluster = createCluster() + cluster.Spec.ProcessCounts.Storage = 2 + cluster.Status.ProcessGroups[0].MarkForRemoval() + cluster.Status.ProcessGroups[0].UpdateCondition(ResourcesTerminating, true, nil, "") + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeTrue()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 2, + HasPendingRemoval: 2, + })) - cluster = createCluster() - cluster.Spec.ProcessCounts.Storage = 2 - cluster.Status.ProcessGroups[0].MarkForRemoval() - cluster.Status.ProcessGroups[0].SetExclude() - cluster.Status.ProcessGroups[0].UpdateCondition(IncorrectCommandLine, true, nil, "") - cluster.Status.ProcessGroups[0].UpdateCondition(ResourcesTerminating, true, nil, "") - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeTrue()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 2, - HasPendingRemoval: 2, - })) + cluster = createCluster() + cluster.Spec.ProcessCounts.Storage = 2 + cluster.Status.ProcessGroups[0].MarkForRemoval() + cluster.Status.ProcessGroups[0].SetExclude() + cluster.Status.ProcessGroups[0].UpdateCondition(IncorrectCommandLine, true, nil, "") + cluster.Status.ProcessGroups[0].UpdateCondition(ResourcesTerminating, true, nil, "") + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeTrue()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 2, + HasPendingRemoval: 2, + })) - cluster = createCluster() - cluster.Status.HasIncorrectServiceConfig = true - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeFalse()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 1, - NeedsServiceUpdate: 2, - })) + cluster = createCluster() + cluster.Status.HasIncorrectServiceConfig = true + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsServiceUpdate: 2, + })) - cluster = createCluster() - cluster.Status.NeedsNewCoordinators = true - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeFalse()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 1, - NeedsCoordinatorChange: 2, - })) + cluster = createCluster() + cluster.Status.NeedsNewCoordinators = true + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsCoordinatorChange: 2, + })) - cluster = createCluster() - cluster.Status.ProcessGroups[0].UpdateCondition(IncorrectCommandLine, true, nil, "") - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeFalse()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 1, - HasUnhealthyProcess: 2, - })) + cluster = createCluster() + cluster.Status.ProcessGroups[0].UpdateCondition(IncorrectCommandLine, true, nil, "") + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + HasUnhealthyProcess: 2, + })) - cluster = createCluster() - cluster.Spec.LockOptions.DenyList = append(cluster.Spec.LockOptions.DenyList, LockDenyListEntry{ID: "dc1"}) - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeFalse()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 1, - NeedsLockConfigurationChanges: 2, - })) + cluster = createCluster() + cluster.Spec.LockOptions.DenyList = append(cluster.Spec.LockOptions.DenyList, LockDenyListEntry{ID: "dc1"}) + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsLockConfigurationChanges: 2, + })) - cluster = createCluster() - cluster.Spec.LockOptions.DenyList = append(cluster.Spec.LockOptions.DenyList, LockDenyListEntry{ID: "dc1"}) - cluster.Status.Locks.DenyList = []string{"dc1", "dc2"} - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeTrue()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 2, - })) + cluster = createCluster() + cluster.Spec.LockOptions.DenyList = append(cluster.Spec.LockOptions.DenyList, LockDenyListEntry{ID: "dc1"}) + cluster.Status.Locks.DenyList = []string{"dc1", "dc2"} + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeTrue()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 2, + })) - cluster = createCluster() - cluster.Spec.LockOptions.DenyList = append(cluster.Spec.LockOptions.DenyList, LockDenyListEntry{ID: "dc1", Allow: true}) - cluster.Status.Locks.DenyList = []string{"dc1", "dc2"} - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeFalse()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 1, - NeedsLockConfigurationChanges: 2, - })) + cluster = createCluster() + cluster.Spec.LockOptions.DenyList = append(cluster.Spec.LockOptions.DenyList, LockDenyListEntry{ID: "dc1", Allow: true}) + cluster.Status.Locks.DenyList = []string{"dc1", "dc2"} + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeFalse()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 1, + NeedsLockConfigurationChanges: 2, + })) - cluster = createCluster() - cluster.Spec.LockOptions.DenyList = append(cluster.Spec.LockOptions.DenyList, LockDenyListEntry{ID: "dc1", Allow: true}) - result, err = cluster.CheckReconciliation(log) - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(BeTrue()) - Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ - Reconciled: 2, - })) + cluster = createCluster() + cluster.Spec.LockOptions.DenyList = append(cluster.Spec.LockOptions.DenyList, LockDenyListEntry{ID: "dc1", Allow: true}) + result, err = cluster.CheckReconciliation(log) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeTrue()) + Expect(cluster.Status.Generations).To(Equal(ClusterGenerationStatus{ + Reconciled: 2, + })) + }) }) + }) When("getting the process settings", func() { diff --git a/controllers/admin_client_mock.go b/controllers/admin_client_mock.go index 32801d54f..ffa5d0525 100644 --- a/controllers/admin_client_mock.go +++ b/controllers/admin_client_mock.go @@ -315,11 +315,22 @@ func (client *mockAdminClient) GetStatus() (*fdbv1beta2.FoundationDBStatus, erro } // ConfigureDatabase changes the database configuration -func (client *mockAdminClient) ConfigureDatabase(configuration fdbv1beta2.DatabaseConfiguration, _ bool, _ string) error { +func (client *mockAdminClient) ConfigureDatabase(configuration fdbv1beta2.DatabaseConfiguration, _ bool, version string) error { adminClientMutex.Lock() defer adminClientMutex.Unlock() client.DatabaseConfiguration = configuration.DeepCopy() + + ver, err := fdbv1beta2.ParseFdbVersion(version) + if err != nil { + return err + } + + if !ver.HasSeparatedProxies() { + client.DatabaseConfiguration.GrvProxies = 0 + client.DatabaseConfiguration.CommitProxies = 0 + } + return nil } diff --git a/controllers/admin_client_test.go b/controllers/admin_client_test.go index d9ab6ded0..70ea5c134 100644 --- a/controllers/admin_client_test.go +++ b/controllers/admin_client_test.go @@ -65,48 +65,109 @@ var _ = Describe("admin_client_test", func() { }) Context("with a basic cluster", func() { - It("should generate the status", func() { - Expect(status.Cluster.DatabaseConfiguration).To(Equal(fdbv1beta2.DatabaseConfiguration{ - RedundancyMode: fdbv1beta2.RedundancyModeDouble, - StorageEngine: "ssd-2", - UsableRegions: 1, - RoleCounts: fdbv1beta2.RoleCounts{ - Logs: 3, - Proxies: 3, - CommitProxies: 2, - GrvProxies: 1, - Resolvers: 1, - LogRouters: -1, - RemoteLogs: -1, - }, - VersionFlags: fdbv1beta2.VersionFlags{ - LogSpill: 2, - }, - })) + When("the version supports grv and commit proxies", func() { + BeforeEach(func() { + cluster.Spec.Version = fdbv1beta2.Versions.NextMajorVersion.String() + err = k8sClient.Update(context.TODO(), cluster) + Expect(err).NotTo(HaveOccurred()) - address := cluster.Status.ProcessGroups[13].Addresses[0] - Expect(status.Cluster.Processes).To(HaveLen(len(cluster.Status.ProcessGroups))) - Expect(status.Cluster.Processes["operator-test-1-storage-1-1"]).To(Equal(fdbv1beta2.FoundationDBStatusProcessInfo{ - Address: fdbv1beta2.ProcessAddress{ - IPAddress: net.ParseIP(address), - Port: 4501, - }, - ProcessClass: fdbv1beta2.ProcessClassStorage, - CommandLine: fmt.Sprintf("/usr/bin/fdbserver --class=storage --cluster_file=/var/fdb/data/fdb.cluster --datadir=/var/fdb/data --listen_address=%s:4501 --locality_instance_id=storage-1 --locality_machineid=operator-test-1-storage-1 --locality_zoneid=operator-test-1-storage-1 --logdir=/var/log/fdb-trace-logs --loggroup=operator-test-1 --public_address=%s:4501 --seed_cluster_file=/var/dynamic-conf/fdb.cluster", address, address), - Excluded: false, - Locality: map[string]string{ - "instance_id": "storage-1", - "zoneid": "operator-test-1-storage-1", - "dcid": "", - }, - Version: "6.2.20", - UptimeSeconds: 60000, - Roles: []fdbv1beta2.FoundationDBStatusProcessRoleInfo{ - { - Role: string(fdbv1beta2.ProcessRoleCoordinator), + result, err := reconcileCluster(cluster) + Expect(err).NotTo(HaveOccurred()) + Expect(result.Requeue).To(BeFalse()) + + generation, err := reloadCluster(cluster) + Expect(err).NotTo(HaveOccurred()) + Expect(generation).NotTo(Equal(int64(0))) + + client, err = newMockAdminClientUncast(cluster, k8sClient) + Expect(err).NotTo(HaveOccurred()) + }) + + It("should generate the status", func() { + Expect(status.Cluster.DatabaseConfiguration).To(Equal(fdbv1beta2.DatabaseConfiguration{ + RedundancyMode: fdbv1beta2.RedundancyModeDouble, + StorageEngine: "ssd-2", + UsableRegions: 1, + RoleCounts: fdbv1beta2.RoleCounts{ + Logs: 3, + Proxies: 3, + CommitProxies: 2, + GrvProxies: 1, + Resolvers: 1, + LogRouters: -1, + RemoteLogs: -1, }, - }, - })) + VersionFlags: fdbv1beta2.VersionFlags{ + LogSpill: 2, + }, + })) + + address := cluster.Status.ProcessGroups[13].Addresses[0] + Expect(status.Cluster.Processes).To(HaveLen(len(cluster.Status.ProcessGroups))) + Expect(status.Cluster.Processes["operator-test-1-storage-1-1"]).To(Equal(fdbv1beta2.FoundationDBStatusProcessInfo{ + Address: fdbv1beta2.ProcessAddress{ + IPAddress: net.ParseIP(address), + Port: 4501, + }, + ProcessClass: fdbv1beta2.ProcessClassStorage, + CommandLine: fmt.Sprintf("/usr/bin/fdbserver --class=storage --cluster_file=/var/fdb/data/fdb.cluster --datadir=/var/fdb/data --listen_address=%s:4501 --locality_instance_id=storage-1 --locality_machineid=operator-test-1-storage-1 --locality_zoneid=operator-test-1-storage-1 --logdir=/var/log/fdb-trace-logs --loggroup=operator-test-1 --public_address=%s:4501 --seed_cluster_file=/var/dynamic-conf/fdb.cluster", address, address), + Excluded: false, + Locality: map[string]string{ + "instance_id": "storage-1", + "zoneid": "operator-test-1-storage-1", + "dcid": "", + }, + Version: fdbv1beta2.Versions.NextMajorVersion.String(), + UptimeSeconds: 60000, + Roles: nil, + })) + }) + }) + + When("the version does not supports grv and commit proxies", func() { + It("should generate the status", func() { + Expect(status.Cluster.DatabaseConfiguration).To(Equal(fdbv1beta2.DatabaseConfiguration{ + RedundancyMode: fdbv1beta2.RedundancyModeDouble, + StorageEngine: "ssd-2", + UsableRegions: 1, + RoleCounts: fdbv1beta2.RoleCounts{ + Logs: 3, + Proxies: 3, + CommitProxies: 0, + GrvProxies: 0, + Resolvers: 1, + LogRouters: -1, + RemoteLogs: -1, + }, + VersionFlags: fdbv1beta2.VersionFlags{ + LogSpill: 2, + }, + })) + + address := cluster.Status.ProcessGroups[13].Addresses[0] + Expect(status.Cluster.Processes).To(HaveLen(len(cluster.Status.ProcessGroups))) + Expect(status.Cluster.Processes["operator-test-1-storage-1-1"]).To(Equal(fdbv1beta2.FoundationDBStatusProcessInfo{ + Address: fdbv1beta2.ProcessAddress{ + IPAddress: net.ParseIP(address), + Port: 4501, + }, + ProcessClass: fdbv1beta2.ProcessClassStorage, + CommandLine: fmt.Sprintf("/usr/bin/fdbserver --class=storage --cluster_file=/var/fdb/data/fdb.cluster --datadir=/var/fdb/data --listen_address=%s:4501 --locality_instance_id=storage-1 --locality_machineid=operator-test-1-storage-1 --locality_zoneid=operator-test-1-storage-1 --logdir=/var/log/fdb-trace-logs --loggroup=operator-test-1 --public_address=%s:4501 --seed_cluster_file=/var/dynamic-conf/fdb.cluster", address, address), + Excluded: false, + Locality: map[string]string{ + "instance_id": "storage-1", + "zoneid": "operator-test-1-storage-1", + "dcid": "", + }, + Version: "6.2.20", + UptimeSeconds: 60000, + Roles: []fdbv1beta2.FoundationDBStatusProcessRoleInfo{ + { + Role: string(fdbv1beta2.ProcessRoleCoordinator), + }, + }, + })) + }) }) }) diff --git a/controllers/cluster_controller_test.go b/controllers/cluster_controller_test.go index 9f00d655f..9af0eda70 100644 --- a/controllers/cluster_controller_test.go +++ b/controllers/cluster_controller_test.go @@ -228,14 +228,29 @@ var _ = Describe("cluster_controller", func() { Expect(adminClient.DatabaseConfiguration.RoleCounts).To(Equal(fdbv1beta2.RoleCounts{ Logs: 3, Proxies: 3, - CommitProxies: 2, - GrvProxies: 1, + CommitProxies: 0, + GrvProxies: 0, Resolvers: 1, RemoteLogs: -1, LogRouters: -1, })) }) + It("should send the configuration to the cluster", func() { + adminClient, err := newMockAdminClientUncast(cluster, k8sClient) + Expect(err).NotTo(HaveOccurred()) + Expect(adminClient).NotTo(BeNil()) + Expect(adminClient.DatabaseConfiguration.RedundancyMode).To(Equal(fdbv1beta2.RedundancyModeDouble)) + Expect(adminClient.DatabaseConfiguration.StorageEngine).To(Equal(fdbv1beta2.StorageEngineSSD2)) + Expect(adminClient.DatabaseConfiguration.RoleCounts).To(Equal(fdbv1beta2.RoleCounts{ + Logs: 3, + Proxies: 3, + Resolvers: 1, + RemoteLogs: -1, + LogRouters: -1, + })) + }) + It("should update the status with the reconciliation result", func() { adminClient, err := newMockAdminClientUncast(cluster, k8sClient) Expect(err).NotTo(HaveOccurred())