Skip to content

Commit 5878ddc

Browse files
authored
CLOUDP-201083: Improve validation and handling of advanced deployments (#1146)
1 parent 0cf936b commit 5878ddc

File tree

10 files changed

+1589
-932
lines changed

10 files changed

+1589
-932
lines changed

pkg/controller/atlasdeployment/advanced_deployment.go

Lines changed: 18 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,6 @@ func (r *AtlasDeploymentReconciler) ensureAdvancedDeploymentState(ctx *workflow.
7878
}
7979

8080
func advancedDeploymentIdle(ctx *workflow.Context, project *mdbv1.AtlasProject, deployment *mdbv1.AtlasDeployment, atlasDeploymentAsAtlas *mongodbatlas.AdvancedCluster) (*mongodbatlas.AdvancedCluster, workflow.Result) {
81-
err := handleAutoscaling(ctx, deployment.Spec.AdvancedDeploymentSpec, atlasDeploymentAsAtlas)
82-
if err != nil {
83-
return atlasDeploymentAsAtlas, workflow.Terminate(workflow.Internal, err.Error())
84-
}
85-
8681
specDeployment, atlasDeployment, err := MergedAdvancedDeployment(*atlasDeploymentAsAtlas, *deployment.Spec.AdvancedDeploymentSpec)
8782
if err != nil {
8883
return atlasDeploymentAsAtlas, workflow.Terminate(workflow.Internal, err.Error())
@@ -105,7 +100,7 @@ func advancedDeploymentIdle(ctx *workflow.Context, project *mdbv1.AtlasProject,
105100
}
106101
}
107102

108-
cleanupTheSpec(ctx, &specDeployment)
103+
syncRegionConfiguration(&specDeployment, atlasDeploymentAsAtlas)
109104

110105
deploymentAsAtlas, err := specDeployment.ToAtlas()
111106
if err != nil {
@@ -120,132 +115,19 @@ func advancedDeploymentIdle(ctx *workflow.Context, project *mdbv1.AtlasProject,
120115
return nil, workflow.InProgress(workflow.DeploymentUpdating, "deployment is updating")
121116
}
122117

123-
func cleanupTheSpec(ctx *workflow.Context, specMerged *mdbv1.AdvancedDeploymentSpec) {
124-
specMerged.MongoDBVersion = ""
125-
126-
globalInstanceSize := ""
127-
for i, replicationSpec := range specMerged.ReplicationSpecs {
128-
autoScalingMissing := false
129-
applyToEach(replicationSpec.RegionConfigs, func(config *mdbv1.AdvancedRegionConfig) {
130-
if config.AutoScaling == nil {
131-
autoScalingMissing = true
132-
}
133-
})
134-
135-
if autoScalingMissing {
136-
ctx.Log.Debug("Not all RegionConfigs have AutoScaling set after object merge, removing it everywhere")
137-
applyToEach(replicationSpec.RegionConfigs, func(config *mdbv1.AdvancedRegionConfig) {
138-
config.AutoScaling = nil
139-
})
140-
}
141-
142-
for k := range replicationSpec.RegionConfigs {
143-
regionConfig := specMerged.ReplicationSpecs[i].RegionConfigs[k]
144-
145-
specs := []*mdbv1.Specs{
146-
regionConfig.AnalyticsSpecs,
147-
regionConfig.ElectableSpecs,
148-
regionConfig.ReadOnlySpecs,
149-
}
150-
151-
applyToEach(specs, func(spec *mdbv1.Specs) {
152-
if globalInstanceSize == "" && spec.NodeCount != nil && *spec.NodeCount != 0 {
153-
globalInstanceSize = spec.InstanceSize
154-
}
155-
})
156-
157-
applyToEach(specs, func(spec *mdbv1.Specs) {
158-
if spec.NodeCount == nil || *spec.NodeCount == 0 {
159-
spec.InstanceSize = globalInstanceSize
160-
}
161-
})
162-
163-
if !autoScalingMissing && regionConfig.AutoScaling.Compute != nil && (regionConfig.AutoScaling.Compute.Enabled == nil || !*regionConfig.AutoScaling.Compute.Enabled) {
164-
regionConfig.AutoScaling.Compute.MinInstanceSize = ""
165-
regionConfig.AutoScaling.Compute.MaxInstanceSize = ""
166-
}
167-
}
168-
}
169-
}
170-
171-
func applyToEach[T any](items []*T, f func(spec *T)) {
172-
for _, item := range items {
173-
if item != nil {
174-
f(item)
175-
}
176-
}
177-
}
178-
179-
// This will prevent from setting diskSizeGB if at least one region config has enabled disk size autoscaling
180-
// It will also prevent from setting ANY of (electable | analytics | readonly) specs
181-
//
182-
// if region config has enabled compute autoscaling
183-
func handleAutoscaling(ctx *workflow.Context, desiredDeployment *mdbv1.AdvancedDeploymentSpec, currentDeployment *mongodbatlas.AdvancedCluster) error {
184-
isDiskAutoScaled := false
185-
syncInstanceSize := func(s *mdbv1.Specs, as *mdbv1.AdvancedAutoScalingSpec) error {
186-
if s != nil {
187-
size, err := normalizeInstanceSize(ctx, s.InstanceSize, as)
188-
if err != nil {
189-
return err
190-
}
191-
192-
if isInstanceSizeTheSame(currentDeployment, size) {
193-
size = ""
194-
}
195-
196-
s.InstanceSize = size
197-
}
198-
199-
return nil
200-
}
201-
for _, repSpec := range desiredDeployment.ReplicationSpecs {
202-
for _, regConfig := range repSpec.RegionConfigs {
203-
if regConfig.AutoScaling != nil {
204-
if regConfig.AutoScaling.DiskGB != nil &&
205-
regConfig.AutoScaling.DiskGB.Enabled != nil &&
206-
*regConfig.AutoScaling.DiskGB.Enabled {
207-
isDiskAutoScaled = true
208-
}
209-
210-
if regConfig.AutoScaling.Compute != nil &&
211-
regConfig.AutoScaling.Compute.Enabled != nil &&
212-
*regConfig.AutoScaling.Compute.Enabled {
213-
err := syncInstanceSize(regConfig.ElectableSpecs, regConfig.AutoScaling)
214-
if err != nil {
215-
return err
216-
}
217-
218-
err = syncInstanceSize(regConfig.AnalyticsSpecs, regConfig.AutoScaling)
219-
if err != nil {
220-
return err
221-
}
222-
223-
err = syncInstanceSize(regConfig.ReadOnlySpecs, regConfig.AutoScaling)
224-
if err != nil {
225-
return err
226-
}
227-
}
228-
}
229-
}
230-
}
231-
232-
if isDiskAutoScaled {
233-
desiredDeployment.DiskSizeGB = nil
234-
}
235-
236-
return nil
237-
}
238-
239118
// MergedAdvancedDeployment will return the result of merging AtlasDeploymentSpec with Atlas Advanced Deployment
240119
func MergedAdvancedDeployment(atlasDeploymentAsAtlas mongodbatlas.AdvancedCluster, specDeployment mdbv1.AdvancedDeploymentSpec) (mergedDeployment mdbv1.AdvancedDeploymentSpec, atlasDeployment mdbv1.AdvancedDeploymentSpec, err error) {
241120
if IsFreeTierAdvancedDeployment(&atlasDeploymentAsAtlas) {
242121
atlasDeploymentAsAtlas.DiskSizeGB = nil
243122
}
123+
244124
atlasDeployment, err = AdvancedDeploymentFromAtlas(atlasDeploymentAsAtlas)
245125
if err != nil {
246126
return
247127
}
248128

129+
normalizeSpecs(specDeployment.ReplicationSpecs[0].RegionConfigs)
130+
249131
mergedDeployment = mdbv1.AdvancedDeploymentSpec{}
250132

251133
if err = compat.JSONCopy(&mergedDeployment, atlasDeployment); err != nil {
@@ -260,11 +142,15 @@ func MergedAdvancedDeployment(atlasDeploymentAsAtlas mongodbatlas.AdvancedCluste
260142
for k, v := range replicationSpec.RegionConfigs {
261143
// the response does not return backing provider names in some situations.
262144
// if this is the case, we want to strip these fields so they do not cause a bad comparison.
263-
if v.BackingProviderName == "" {
145+
if v.BackingProviderName == "" && k < len(mergedDeployment.ReplicationSpecs[i].RegionConfigs) {
264146
mergedDeployment.ReplicationSpecs[i].RegionConfigs[k].BackingProviderName = ""
265147
}
266148
}
267149
}
150+
151+
atlasDeployment.MongoDBVersion = ""
152+
mergedDeployment.MongoDBVersion = ""
153+
268154
return
269155
}
270156

@@ -329,15 +215,21 @@ func cleanupFieldsToCompare(atlas, operator mdbv1.AdvancedDeploymentSpec) mdbv1.
329215

330216
for configIdx, regionConfig := range replicationSpec.RegionConfigs {
331217
if regionConfig.AnalyticsSpecs == nil || regionConfig.AnalyticsSpecs.NodeCount == nil || *regionConfig.AnalyticsSpecs.NodeCount == 0 {
332-
regionConfig.AnalyticsSpecs = operator.ReplicationSpecs[specIdx].RegionConfigs[configIdx].AnalyticsSpecs
218+
if configIdx < len(operator.ReplicationSpecs[specIdx].RegionConfigs) {
219+
regionConfig.AnalyticsSpecs = operator.ReplicationSpecs[specIdx].RegionConfigs[configIdx].AnalyticsSpecs
220+
}
333221
}
334222

335223
if regionConfig.ElectableSpecs == nil || regionConfig.ElectableSpecs.NodeCount == nil || *regionConfig.ElectableSpecs.NodeCount == 0 {
336-
regionConfig.ElectableSpecs = operator.ReplicationSpecs[specIdx].RegionConfigs[configIdx].ElectableSpecs
224+
if configIdx < len(operator.ReplicationSpecs[specIdx].RegionConfigs) {
225+
regionConfig.ElectableSpecs = operator.ReplicationSpecs[specIdx].RegionConfigs[configIdx].ElectableSpecs
226+
}
337227
}
338228

339229
if regionConfig.ReadOnlySpecs == nil || regionConfig.ReadOnlySpecs.NodeCount == nil || *regionConfig.ReadOnlySpecs.NodeCount == 0 {
340-
regionConfig.ReadOnlySpecs = operator.ReplicationSpecs[specIdx].RegionConfigs[configIdx].ReadOnlySpecs
230+
if configIdx < len(operator.ReplicationSpecs[specIdx].RegionConfigs) {
231+
regionConfig.ReadOnlySpecs = operator.ReplicationSpecs[specIdx].RegionConfigs[configIdx].ReadOnlySpecs
232+
}
341233
}
342234
}
343235
}
@@ -361,39 +253,6 @@ func GetAllDeploymentNames(client mongodbatlas.Client, projectID string) ([]stri
361253
return deploymentNames, nil
362254
}
363255

364-
func normalizeInstanceSize(ctx *workflow.Context, currentInstanceSize string, autoscaling *mdbv1.AdvancedAutoScalingSpec) (string, error) {
365-
currentSize, err := NewFromInstanceSizeName(currentInstanceSize)
366-
if err != nil {
367-
return "", err
368-
}
369-
370-
minSize, err := NewFromInstanceSizeName(autoscaling.Compute.MinInstanceSize)
371-
if err != nil {
372-
return "", err
373-
}
374-
375-
maxSize, err := NewFromInstanceSizeName(autoscaling.Compute.MaxInstanceSize)
376-
if err != nil {
377-
return "", err
378-
}
379-
380-
if CompareInstanceSizes(currentSize, minSize) == -1 {
381-
ctx.Log.Warnf("The instance size is below the minimum autoscaling configuration. Setting it to %s. Consider update your CRD", autoscaling.Compute.MinInstanceSize)
382-
return autoscaling.Compute.MinInstanceSize, nil
383-
}
384-
385-
if CompareInstanceSizes(currentSize, maxSize) == 1 {
386-
ctx.Log.Warnf("The instance size is above the maximum autoscaling configuration. Setting it to %s. Consider update your CRD", autoscaling.Compute.MaxInstanceSize)
387-
return autoscaling.Compute.MaxInstanceSize, nil
388-
}
389-
390-
return currentInstanceSize, nil
391-
}
392-
393-
func isInstanceSizeTheSame(currentDeployment *mongodbatlas.AdvancedCluster, desiredInstanceSize string) bool {
394-
return desiredInstanceSize == currentDeployment.ReplicationSpecs[0].RegionConfigs[0].ElectableSpecs.InstanceSize
395-
}
396-
397256
func (r *AtlasDeploymentReconciler) ensureConnectionSecrets(ctx *workflow.Context, project *mdbv1.AtlasProject, name string, connectionStrings *mongodbatlas.ConnectionStrings, deploymentResource *mdbv1.AtlasDeployment) workflow.Result {
398257
databaseUsers := mdbv1.AtlasDatabaseUserList{}
399258
err := r.Client.List(context.TODO(), &databaseUsers, &client.ListOptions{})

0 commit comments

Comments
 (0)