From 5878ddc8e1a51a75257d4474820f3d2ded6cb0a3 Mon Sep 17 00:00:00 2001 From: Helder Santana Date: Thu, 5 Oct 2023 23:54:59 +0200 Subject: [PATCH] CLOUDP-201083: Improve validation and handling of advanced deployments (#1146) --- .../atlasdeployment/advanced_deployment.go | 177 +--- .../advanced_deployment_test.go | 742 ------------- pkg/controller/atlasdeployment/deployment.go | 36 +- .../atlasdeployment/region_configuration.go | 141 +++ .../region_configuration_test.go | 981 ++++++++++++++++++ .../instance_size.go | 10 +- .../instance_size_test.go | 2 +- pkg/controller/validate/validate.go | 117 ++- pkg/controller/validate/validate_test.go | 289 ++++++ test/int/deployment_test.go | 26 +- 10 files changed, 1589 insertions(+), 932 deletions(-) create mode 100644 pkg/controller/atlasdeployment/region_configuration.go create mode 100644 pkg/controller/atlasdeployment/region_configuration_test.go rename pkg/controller/{atlasdeployment => validate}/instance_size.go (86%) rename pkg/controller/{atlasdeployment => validate}/instance_size_test.go (99%) diff --git a/pkg/controller/atlasdeployment/advanced_deployment.go b/pkg/controller/atlasdeployment/advanced_deployment.go index 492a029d60..d54599b3d3 100644 --- a/pkg/controller/atlasdeployment/advanced_deployment.go +++ b/pkg/controller/atlasdeployment/advanced_deployment.go @@ -78,11 +78,6 @@ func (r *AtlasDeploymentReconciler) ensureAdvancedDeploymentState(ctx *workflow. } func advancedDeploymentIdle(ctx *workflow.Context, project *mdbv1.AtlasProject, deployment *mdbv1.AtlasDeployment, atlasDeploymentAsAtlas *mongodbatlas.AdvancedCluster) (*mongodbatlas.AdvancedCluster, workflow.Result) { - err := handleAutoscaling(ctx, deployment.Spec.AdvancedDeploymentSpec, atlasDeploymentAsAtlas) - if err != nil { - return atlasDeploymentAsAtlas, workflow.Terminate(workflow.Internal, err.Error()) - } - specDeployment, atlasDeployment, err := MergedAdvancedDeployment(*atlasDeploymentAsAtlas, *deployment.Spec.AdvancedDeploymentSpec) if err != nil { return atlasDeploymentAsAtlas, workflow.Terminate(workflow.Internal, err.Error()) @@ -105,7 +100,7 @@ func advancedDeploymentIdle(ctx *workflow.Context, project *mdbv1.AtlasProject, } } - cleanupTheSpec(ctx, &specDeployment) + syncRegionConfiguration(&specDeployment, atlasDeploymentAsAtlas) deploymentAsAtlas, err := specDeployment.ToAtlas() if err != nil { @@ -120,132 +115,19 @@ func advancedDeploymentIdle(ctx *workflow.Context, project *mdbv1.AtlasProject, return nil, workflow.InProgress(workflow.DeploymentUpdating, "deployment is updating") } -func cleanupTheSpec(ctx *workflow.Context, specMerged *mdbv1.AdvancedDeploymentSpec) { - specMerged.MongoDBVersion = "" - - globalInstanceSize := "" - for i, replicationSpec := range specMerged.ReplicationSpecs { - autoScalingMissing := false - applyToEach(replicationSpec.RegionConfigs, func(config *mdbv1.AdvancedRegionConfig) { - if config.AutoScaling == nil { - autoScalingMissing = true - } - }) - - if autoScalingMissing { - ctx.Log.Debug("Not all RegionConfigs have AutoScaling set after object merge, removing it everywhere") - applyToEach(replicationSpec.RegionConfigs, func(config *mdbv1.AdvancedRegionConfig) { - config.AutoScaling = nil - }) - } - - for k := range replicationSpec.RegionConfigs { - regionConfig := specMerged.ReplicationSpecs[i].RegionConfigs[k] - - specs := []*mdbv1.Specs{ - regionConfig.AnalyticsSpecs, - regionConfig.ElectableSpecs, - regionConfig.ReadOnlySpecs, - } - - applyToEach(specs, func(spec *mdbv1.Specs) { - if globalInstanceSize == "" && spec.NodeCount != nil && *spec.NodeCount != 0 { - globalInstanceSize = spec.InstanceSize - } - }) - - applyToEach(specs, func(spec *mdbv1.Specs) { - if spec.NodeCount == nil || *spec.NodeCount == 0 { - spec.InstanceSize = globalInstanceSize - } - }) - - if !autoScalingMissing && regionConfig.AutoScaling.Compute != nil && (regionConfig.AutoScaling.Compute.Enabled == nil || !*regionConfig.AutoScaling.Compute.Enabled) { - regionConfig.AutoScaling.Compute.MinInstanceSize = "" - regionConfig.AutoScaling.Compute.MaxInstanceSize = "" - } - } - } -} - -func applyToEach[T any](items []*T, f func(spec *T)) { - for _, item := range items { - if item != nil { - f(item) - } - } -} - -// This will prevent from setting diskSizeGB if at least one region config has enabled disk size autoscaling -// It will also prevent from setting ANY of (electable | analytics | readonly) specs -// -// if region config has enabled compute autoscaling -func handleAutoscaling(ctx *workflow.Context, desiredDeployment *mdbv1.AdvancedDeploymentSpec, currentDeployment *mongodbatlas.AdvancedCluster) error { - isDiskAutoScaled := false - syncInstanceSize := func(s *mdbv1.Specs, as *mdbv1.AdvancedAutoScalingSpec) error { - if s != nil { - size, err := normalizeInstanceSize(ctx, s.InstanceSize, as) - if err != nil { - return err - } - - if isInstanceSizeTheSame(currentDeployment, size) { - size = "" - } - - s.InstanceSize = size - } - - return nil - } - for _, repSpec := range desiredDeployment.ReplicationSpecs { - for _, regConfig := range repSpec.RegionConfigs { - if regConfig.AutoScaling != nil { - if regConfig.AutoScaling.DiskGB != nil && - regConfig.AutoScaling.DiskGB.Enabled != nil && - *regConfig.AutoScaling.DiskGB.Enabled { - isDiskAutoScaled = true - } - - if regConfig.AutoScaling.Compute != nil && - regConfig.AutoScaling.Compute.Enabled != nil && - *regConfig.AutoScaling.Compute.Enabled { - err := syncInstanceSize(regConfig.ElectableSpecs, regConfig.AutoScaling) - if err != nil { - return err - } - - err = syncInstanceSize(regConfig.AnalyticsSpecs, regConfig.AutoScaling) - if err != nil { - return err - } - - err = syncInstanceSize(regConfig.ReadOnlySpecs, regConfig.AutoScaling) - if err != nil { - return err - } - } - } - } - } - - if isDiskAutoScaled { - desiredDeployment.DiskSizeGB = nil - } - - return nil -} - // MergedAdvancedDeployment will return the result of merging AtlasDeploymentSpec with Atlas Advanced Deployment func MergedAdvancedDeployment(atlasDeploymentAsAtlas mongodbatlas.AdvancedCluster, specDeployment mdbv1.AdvancedDeploymentSpec) (mergedDeployment mdbv1.AdvancedDeploymentSpec, atlasDeployment mdbv1.AdvancedDeploymentSpec, err error) { if IsFreeTierAdvancedDeployment(&atlasDeploymentAsAtlas) { atlasDeploymentAsAtlas.DiskSizeGB = nil } + atlasDeployment, err = AdvancedDeploymentFromAtlas(atlasDeploymentAsAtlas) if err != nil { return } + normalizeSpecs(specDeployment.ReplicationSpecs[0].RegionConfigs) + mergedDeployment = mdbv1.AdvancedDeploymentSpec{} if err = compat.JSONCopy(&mergedDeployment, atlasDeployment); err != nil { @@ -260,11 +142,15 @@ func MergedAdvancedDeployment(atlasDeploymentAsAtlas mongodbatlas.AdvancedCluste for k, v := range replicationSpec.RegionConfigs { // the response does not return backing provider names in some situations. // if this is the case, we want to strip these fields so they do not cause a bad comparison. - if v.BackingProviderName == "" { + if v.BackingProviderName == "" && k < len(mergedDeployment.ReplicationSpecs[i].RegionConfigs) { mergedDeployment.ReplicationSpecs[i].RegionConfigs[k].BackingProviderName = "" } } } + + atlasDeployment.MongoDBVersion = "" + mergedDeployment.MongoDBVersion = "" + return } @@ -329,15 +215,21 @@ func cleanupFieldsToCompare(atlas, operator mdbv1.AdvancedDeploymentSpec) mdbv1. for configIdx, regionConfig := range replicationSpec.RegionConfigs { if regionConfig.AnalyticsSpecs == nil || regionConfig.AnalyticsSpecs.NodeCount == nil || *regionConfig.AnalyticsSpecs.NodeCount == 0 { - regionConfig.AnalyticsSpecs = operator.ReplicationSpecs[specIdx].RegionConfigs[configIdx].AnalyticsSpecs + if configIdx < len(operator.ReplicationSpecs[specIdx].RegionConfigs) { + regionConfig.AnalyticsSpecs = operator.ReplicationSpecs[specIdx].RegionConfigs[configIdx].AnalyticsSpecs + } } if regionConfig.ElectableSpecs == nil || regionConfig.ElectableSpecs.NodeCount == nil || *regionConfig.ElectableSpecs.NodeCount == 0 { - regionConfig.ElectableSpecs = operator.ReplicationSpecs[specIdx].RegionConfigs[configIdx].ElectableSpecs + if configIdx < len(operator.ReplicationSpecs[specIdx].RegionConfigs) { + regionConfig.ElectableSpecs = operator.ReplicationSpecs[specIdx].RegionConfigs[configIdx].ElectableSpecs + } } if regionConfig.ReadOnlySpecs == nil || regionConfig.ReadOnlySpecs.NodeCount == nil || *regionConfig.ReadOnlySpecs.NodeCount == 0 { - regionConfig.ReadOnlySpecs = operator.ReplicationSpecs[specIdx].RegionConfigs[configIdx].ReadOnlySpecs + if configIdx < len(operator.ReplicationSpecs[specIdx].RegionConfigs) { + regionConfig.ReadOnlySpecs = operator.ReplicationSpecs[specIdx].RegionConfigs[configIdx].ReadOnlySpecs + } } } } @@ -361,39 +253,6 @@ func GetAllDeploymentNames(client mongodbatlas.Client, projectID string) ([]stri return deploymentNames, nil } -func normalizeInstanceSize(ctx *workflow.Context, currentInstanceSize string, autoscaling *mdbv1.AdvancedAutoScalingSpec) (string, error) { - currentSize, err := NewFromInstanceSizeName(currentInstanceSize) - if err != nil { - return "", err - } - - minSize, err := NewFromInstanceSizeName(autoscaling.Compute.MinInstanceSize) - if err != nil { - return "", err - } - - maxSize, err := NewFromInstanceSizeName(autoscaling.Compute.MaxInstanceSize) - if err != nil { - return "", err - } - - if CompareInstanceSizes(currentSize, minSize) == -1 { - ctx.Log.Warnf("The instance size is below the minimum autoscaling configuration. Setting it to %s. Consider update your CRD", autoscaling.Compute.MinInstanceSize) - return autoscaling.Compute.MinInstanceSize, nil - } - - if CompareInstanceSizes(currentSize, maxSize) == 1 { - ctx.Log.Warnf("The instance size is above the maximum autoscaling configuration. Setting it to %s. Consider update your CRD", autoscaling.Compute.MaxInstanceSize) - return autoscaling.Compute.MaxInstanceSize, nil - } - - return currentInstanceSize, nil -} - -func isInstanceSizeTheSame(currentDeployment *mongodbatlas.AdvancedCluster, desiredInstanceSize string) bool { - return desiredInstanceSize == currentDeployment.ReplicationSpecs[0].RegionConfigs[0].ElectableSpecs.InstanceSize -} - func (r *AtlasDeploymentReconciler) ensureConnectionSecrets(ctx *workflow.Context, project *mdbv1.AtlasProject, name string, connectionStrings *mongodbatlas.ConnectionStrings, deploymentResource *mdbv1.AtlasDeployment) workflow.Result { databaseUsers := mdbv1.AtlasDatabaseUserList{} err := r.Client.List(context.TODO(), &databaseUsers, &client.ListOptions{}) diff --git a/pkg/controller/atlasdeployment/advanced_deployment_test.go b/pkg/controller/atlasdeployment/advanced_deployment_test.go index 4239fc95b1..e155d5c41f 100644 --- a/pkg/controller/atlasdeployment/advanced_deployment_test.go +++ b/pkg/controller/atlasdeployment/advanced_deployment_test.go @@ -1,16 +1,11 @@ package atlasdeployment import ( - "encoding/json" - "errors" - "reflect" "testing" "go.uber.org/zap" "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1/common" - "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1/status" - "github.com/mongodb/mongodb-atlas-kubernetes/pkg/controller/workflow" "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/toptr" "github.com/stretchr/testify/assert" @@ -106,743 +101,6 @@ func fillInSpecs(regionConfig *mongodbatlas.AdvancedRegionConfig, instanceSize s } } -func TestAdvancedDeployment_handleAutoscaling(t *testing.T) { - testCases := []struct { - desiredDeployment *mdbv1.AdvancedDeploymentSpec - currentDeployment *mongodbatlas.AdvancedCluster - expected *mdbv1.AdvancedDeploymentSpec - shouldFail bool - testName string - err error - }{ - { - testName: "One region and autoscaling ENABLED for compute AND disk", - desiredDeployment: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: toptr.MakePtr(15), - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "M30", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(true), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: nil, - MinInstanceSize: "M10", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - currentDeployment: &mongodbatlas.AdvancedCluster{ - ReplicationSpecs: []*mongodbatlas.AdvancedReplicationSpec{ - { - RegionConfigs: []*mongodbatlas.AdvancedRegionConfig{ - { - ElectableSpecs: &mongodbatlas.Specs{ - InstanceSize: "M30", - }, - }, - }, - }, - }, - }, - expected: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: nil, - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(true), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: nil, - MinInstanceSize: "M10", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - shouldFail: false, - }, - { - testName: "One region and autoscaling ENABLED for compute ONLY", - desiredDeployment: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: toptr.MakePtr(15), - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "M40", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(false), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: nil, - MinInstanceSize: "M10", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - currentDeployment: &mongodbatlas.AdvancedCluster{ - ReplicationSpecs: []*mongodbatlas.AdvancedReplicationSpec{ - { - RegionConfigs: []*mongodbatlas.AdvancedRegionConfig{ - { - ElectableSpecs: &mongodbatlas.Specs{ - InstanceSize: "M40", - }, - }, - }, - }, - }, - }, - expected: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: toptr.MakePtr(15), - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(false), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: nil, - MinInstanceSize: "M10", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - shouldFail: false, - }, - { - testName: "One region and autoscaling ENABLED for diskGB ONLY", - desiredDeployment: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: toptr.MakePtr(15), - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "M40", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(true), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(false), - ScaleDownEnabled: nil, - MinInstanceSize: "M10", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - expected: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: nil, - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "M40", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(true), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(false), - ScaleDownEnabled: nil, - MinInstanceSize: "M10", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - shouldFail: false, - }, - { - testName: "Two regions and autoscaling ENABLED for compute AND disk in different regions", - desiredDeployment: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: toptr.MakePtr(15), - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - RegionName: "WESTERN_EUROPE", - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "M30", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(true), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: nil, - MinInstanceSize: "M10", - MaxInstanceSize: "M40", - }, - }, - }, - { - RegionName: "EASTERN_EUROPE", - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "M30", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(true), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: nil, - MinInstanceSize: "M10", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - currentDeployment: &mongodbatlas.AdvancedCluster{ - ReplicationSpecs: []*mongodbatlas.AdvancedReplicationSpec{ - { - RegionConfigs: []*mongodbatlas.AdvancedRegionConfig{ - { - ElectableSpecs: &mongodbatlas.Specs{ - InstanceSize: "M30", - }, - }, - { - ElectableSpecs: &mongodbatlas.Specs{ - InstanceSize: "M30", - }, - }, - }, - }, - }, - }, - expected: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: nil, - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - RegionName: "WESTERN_EUROPE", - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(true), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: nil, - MinInstanceSize: "M10", - MaxInstanceSize: "M40", - }, - }, - }, - { - RegionName: "EASTERN_EUROPE", - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(true), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: nil, - MinInstanceSize: "M10", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - shouldFail: false, - }, - { - testName: "One region and autoscaling DISABLED for diskGB AND compute", - desiredDeployment: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: toptr.MakePtr(15), - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "M20", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(false), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(false), - ScaleDownEnabled: nil, - MinInstanceSize: "M10", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - currentDeployment: &mongodbatlas.AdvancedCluster{ - ReplicationSpecs: []*mongodbatlas.AdvancedReplicationSpec{ - { - RegionConfigs: []*mongodbatlas.AdvancedRegionConfig{ - { - ElectableSpecs: &mongodbatlas.Specs{ - InstanceSize: "M20", - }, - }, - }, - }, - }, - }, - expected: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: toptr.MakePtr(15), - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "M20", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(false), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(false), - ScaleDownEnabled: nil, - MinInstanceSize: "M10", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - shouldFail: false, - }, - { - testName: "One regions and autoscaling ENABLED for compute and InstanceSize outside of min boundary", - desiredDeployment: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: toptr.MakePtr(15), - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - RegionName: "WESTERN_EUROPE", - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "M10", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(true), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: nil, - MinInstanceSize: "M20", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - currentDeployment: &mongodbatlas.AdvancedCluster{ - ReplicationSpecs: []*mongodbatlas.AdvancedReplicationSpec{ - { - RegionConfigs: []*mongodbatlas.AdvancedRegionConfig{ - { - ElectableSpecs: &mongodbatlas.Specs{ - InstanceSize: "M10", - }, - }, - }, - }, - }, - }, - expected: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: nil, - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - RegionName: "WESTERN_EUROPE", - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "M20", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(true), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: nil, - MinInstanceSize: "M20", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - shouldFail: false, - }, - { - testName: "One regions and autoscaling ENABLED for compute and InstanceSize outside of max boundary", - desiredDeployment: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: toptr.MakePtr(15), - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - RegionName: "WESTERN_EUROPE", - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "M50", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(true), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: nil, - MinInstanceSize: "M10", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - currentDeployment: &mongodbatlas.AdvancedCluster{ - ReplicationSpecs: []*mongodbatlas.AdvancedReplicationSpec{ - { - RegionConfigs: []*mongodbatlas.AdvancedRegionConfig{ - { - ElectableSpecs: &mongodbatlas.Specs{ - InstanceSize: "M50", - }, - }, - }, - }, - }, - }, - expected: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: nil, - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - RegionName: "WESTERN_EUROPE", - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "M40", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(true), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: nil, - MinInstanceSize: "M10", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - shouldFail: false, - }, - { - testName: "One region and autoscaling with wrong configuration", - desiredDeployment: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: toptr.MakePtr(15), - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "M30", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(true), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: nil, - MinInstanceSize: "S10", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - currentDeployment: &mongodbatlas.AdvancedCluster{ - ReplicationSpecs: []*mongodbatlas.AdvancedReplicationSpec{ - { - RegionConfigs: []*mongodbatlas.AdvancedRegionConfig{ - { - ElectableSpecs: &mongodbatlas.Specs{ - InstanceSize: "M30", - }, - }, - }, - }, - }, - }, - expected: &mdbv1.AdvancedDeploymentSpec{ - DiskSizeGB: nil, - ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ - { - NumShards: 1, - ZoneName: "us-east-1", - RegionConfigs: []*mdbv1.AdvancedRegionConfig{ - { - ElectableSpecs: &mdbv1.Specs{ - DiskIOPS: nil, - EbsVolumeType: "", - InstanceSize: "M30", - NodeCount: toptr.MakePtr(1), - }, - AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ - DiskGB: &mdbv1.DiskGB{ - Enabled: toptr.MakePtr(true), - }, - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: nil, - MinInstanceSize: "S10", - MaxInstanceSize: "M40", - }, - }, - }, - }, - }, - }, - }, - shouldFail: true, - err: errors.New("instance size is invalid. instance family should be M or R"), - }, - } - for _, tt := range testCases { - t.Run(tt.testName, func(t *testing.T) { - ctx := workflow.NewContext(zap.S(), []status.Condition{}) - err := handleAutoscaling(ctx, tt.desiredDeployment, tt.currentDeployment) - - assert.Equal(t, tt.err, err) - if !reflect.DeepEqual(tt.desiredDeployment, tt.expected) && !tt.shouldFail { - expJSON, err := json.MarshalIndent(tt.expected, "", " ") - if err != nil { - t.Fatalf("err: %v", err) - } - inpJSON, err := json.MarshalIndent(tt.desiredDeployment, "", " ") - if err != nil { - t.Fatalf("err: %v", err) - } - t.Errorf("FAIL. Expected: %v, Got: %v", string(expJSON), string(inpJSON)) - } - }) - } -} - -func TestNormalizeInstanceSize(t *testing.T) { - t.Run("InstanceSizeName should not change when inside of autoscaling configuration boundaries", func(t *testing.T) { - ctx := workflow.NewContext(zap.S(), []status.Condition{}) - autoscaling := &mdbv1.AdvancedAutoScalingSpec{ - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: toptr.MakePtr(true), - MinInstanceSize: "M10", - MaxInstanceSize: "M30", - }, - } - - size, err := normalizeInstanceSize(ctx, "M10", autoscaling) - - assert.NoError(t, err) - assert.Equal(t, "M10", size) - }) - t.Run("InstanceSizeName should change to minimum size when outside of the bottom autoscaling configuration boundaries", func(t *testing.T) { - ctx := workflow.NewContext(zap.S(), []status.Condition{}) - autoscaling := &mdbv1.AdvancedAutoScalingSpec{ - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: toptr.MakePtr(true), - MinInstanceSize: "M20", - MaxInstanceSize: "M30", - }, - } - - size, err := normalizeInstanceSize(ctx, "M10", autoscaling) - - assert.NoError(t, err) - assert.Equal(t, "M20", size) - }) - t.Run("InstanceSizeName should change to maximum size when outside of the top autoscaling configuration boundaries", func(t *testing.T) { - ctx := workflow.NewContext(zap.S(), []status.Condition{}) - autoscaling := &mdbv1.AdvancedAutoScalingSpec{ - Compute: &mdbv1.ComputeSpec{ - Enabled: toptr.MakePtr(true), - ScaleDownEnabled: toptr.MakePtr(true), - MinInstanceSize: "M20", - MaxInstanceSize: "M30", - }, - } - - size, err := normalizeInstanceSize(ctx, "M40", autoscaling) - - assert.NoError(t, err) - assert.Equal(t, "M30", size) - }) -} - func TestDbUserBelongsToProjects(t *testing.T) { t.Run("Database User refer to a different project name", func(*testing.T) { dbUser := &mdbv1.AtlasDatabaseUser{ diff --git a/pkg/controller/atlasdeployment/deployment.go b/pkg/controller/atlasdeployment/deployment.go index 8fba14136f..e87b2eecf6 100644 --- a/pkg/controller/atlasdeployment/deployment.go +++ b/pkg/controller/atlasdeployment/deployment.go @@ -3,10 +3,14 @@ package atlasdeployment import ( "errors" + "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1/provider" + mdbv1 "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1" "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/toptr" ) +const deploymentProviderTenant provider.ProviderName = "TENANT" + func ConvertLegacyDeployment(deploymentSpec *mdbv1.AtlasDeploymentSpec) error { legacy := deploymentSpec.DeploymentSpec @@ -81,7 +85,7 @@ func convertLegacyReplicationSpecs(legacy *mdbv1.DeploymentSpec) ([]*mdbv1.Advan InstanceSize: legacy.ProviderSettings.InstanceSizeName, NodeCount: convertLegacyInt64(legacyRegionConfig.ReadOnlyNodes), }, - AutoScaling: convertLegacyAutoScaling(legacy.AutoScaling, legacy.ProviderSettings.AutoScaling), + AutoScaling: convertLegacyAutoScaling(legacy.ProviderSettings.ProviderName, legacy.AutoScaling, legacy.ProviderSettings.AutoScaling), BackingProviderName: legacy.ProviderSettings.BackingProviderName, Priority: convertLegacyInt64(legacyRegionConfig.Priority), ProviderName: string(legacy.ProviderSettings.ProviderName), @@ -97,23 +101,35 @@ func convertLegacyReplicationSpecs(legacy *mdbv1.DeploymentSpec) ([]*mdbv1.Advan return result, nil } -func convertLegacyAutoScaling(legacyRoot, legacyPS *mdbv1.AutoScalingSpec) *mdbv1.AdvancedAutoScalingSpec { - if legacyRoot == nil || legacyPS == nil { +func convertLegacyAutoScaling(provider provider.ProviderName, legacyRoot, legacyPS *mdbv1.AutoScalingSpec) *mdbv1.AdvancedAutoScalingSpec { + if provider == deploymentProviderTenant { return nil } autoScaling := &mdbv1.AdvancedAutoScalingSpec{ DiskGB: &mdbv1.DiskGB{ - Enabled: legacyRoot.DiskGBEnabled, + Enabled: toptr.MakePtr(false), }, + Compute: &mdbv1.ComputeSpec{ + Enabled: toptr.MakePtr(false), + ScaleDownEnabled: toptr.MakePtr(false), + }, + } + + if legacyRoot != nil { + autoScaling.DiskGB.Enabled = legacyRoot.DiskGBEnabled } - if legacyRoot.Compute != nil && legacyRoot.Compute.Enabled != nil { - autoScaling.Compute = &mdbv1.ComputeSpec{ - Enabled: legacyRoot.Compute.Enabled, - ScaleDownEnabled: legacyRoot.Compute.ScaleDownEnabled, - MinInstanceSize: emptyIfDisabled(legacyPS.Compute.MinInstanceSize, legacyRoot.Compute.Enabled), - MaxInstanceSize: emptyIfDisabled(legacyPS.Compute.MaxInstanceSize, legacyRoot.Compute.Enabled), + if legacyRoot != nil && legacyRoot.Compute != nil && legacyRoot.Compute.Enabled != nil { + autoScaling.Compute.Enabled = legacyRoot.Compute.Enabled + + if legacyRoot.Compute.ScaleDownEnabled != nil { + autoScaling.Compute.ScaleDownEnabled = legacyRoot.Compute.ScaleDownEnabled + } + + if legacyPS != nil && legacyPS.Compute != nil { + autoScaling.Compute.MinInstanceSize = emptyIfDisabled(legacyPS.Compute.MinInstanceSize, legacyRoot.Compute.Enabled) + autoScaling.Compute.MaxInstanceSize = emptyIfDisabled(legacyPS.Compute.MaxInstanceSize, legacyRoot.Compute.Enabled) } } diff --git a/pkg/controller/atlasdeployment/region_configuration.go b/pkg/controller/atlasdeployment/region_configuration.go new file mode 100644 index 0000000000..9436253d48 --- /dev/null +++ b/pkg/controller/atlasdeployment/region_configuration.go @@ -0,0 +1,141 @@ +package atlasdeployment + +import ( + "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/compat" + "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/toptr" + + "github.com/google/go-cmp/cmp" + "go.mongodb.org/atlas/mongodbatlas" + + mdbv1 "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1" +) + +func syncRegionConfiguration(deploymentSpec *mdbv1.AdvancedDeploymentSpec, atlasCluster *mongodbatlas.AdvancedCluster) { + // When there's no config to handle, do nothing + if deploymentSpec == nil || len(deploymentSpec.ReplicationSpecs) == 0 { + return + } + + // When there's no cluster in Atlas, we need to keep configuration + if atlasCluster == nil || len(atlasCluster.ReplicationSpecs) == 0 { + return + } + + for _, regionSpec := range deploymentSpec.ReplicationSpecs[0].RegionConfigs { + // When disc auto-scaling is enabled and there's no updated on disk size, unset disc size letting auto-scaling config control it + if isDiskAutoScalingEnabled(regionSpec.AutoScaling) && !hasDiskSizeChanged(deploymentSpec.DiskSizeGB, atlasCluster.DiskSizeGB) { + deploymentSpec.DiskSizeGB = nil + } + } + + // when editing a region, normalize change compute configuration + regionsHasChanged := false + if regionsConfigHasChanged(deploymentSpec.ReplicationSpecs[0].RegionConfigs, atlasCluster.ReplicationSpecs[0].RegionConfigs) { + regionsHasChanged = true + normalizeSpecs(deploymentSpec.ReplicationSpecs[0].RegionConfigs) + } + + for _, regionSpec := range deploymentSpec.ReplicationSpecs[0].RegionConfigs { + // When compute auto-scaling is enabled, unset instance size to avoid override production workload + if isComputeAutoScalingEnabled(regionSpec.AutoScaling) { + if !regionsHasChanged { + regionSpec.ElectableSpecs.InstanceSize = "" + regionSpec.ReadOnlySpecs.InstanceSize = "" + regionSpec.AnalyticsSpecs.InstanceSize = "" + } + } else { + if regionSpec.AutoScaling != nil { + regionSpec.AutoScaling.Compute = nil + } + } + } +} + +func isComputeAutoScalingEnabled(autoScalingSpec *mdbv1.AdvancedAutoScalingSpec) bool { + return autoScalingSpec != nil && autoScalingSpec.Compute != nil && autoScalingSpec.Compute.Enabled != nil && *autoScalingSpec.Compute.Enabled +} + +func isDiskAutoScalingEnabled(autoScalingSpec *mdbv1.AdvancedAutoScalingSpec) bool { + return autoScalingSpec != nil && autoScalingSpec.DiskGB != nil && autoScalingSpec.DiskGB.Enabled != nil && *autoScalingSpec.DiskGB.Enabled +} + +func hasDiskSizeChanged(deploymentDiskSize *int, clusterDiskSize *float64) bool { + if deploymentDiskSize == nil && clusterDiskSize == nil { + return false + } + + if deploymentDiskSize == nil && clusterDiskSize != nil { + return true + } + + if deploymentDiskSize != nil && clusterDiskSize == nil { + return true + } + + if *clusterDiskSize < 0 { + return true + } + + return *deploymentDiskSize != int(*clusterDiskSize) +} + +func regionsConfigHasChanged(deploymentRegions []*mdbv1.AdvancedRegionConfig, atlasRegions []*mongodbatlas.AdvancedRegionConfig) bool { + if len(deploymentRegions) != len(atlasRegions) { + return true + } + + mapDeploymentRegions := map[string]*mdbv1.AdvancedRegionConfig{} + for _, region := range deploymentRegions { + mapDeploymentRegions[region.RegionName] = region + } + + for _, region := range atlasRegions { + if _, ok := mapDeploymentRegions[region.RegionName]; !ok { + return true + } + + var atlasAsOperatorRegion mdbv1.AdvancedRegionConfig + err := compat.JSONCopy(&atlasAsOperatorRegion, region) + if err != nil { + return true + } + + if cmp.Diff(mapDeploymentRegions[region.RegionName], &atlasAsOperatorRegion) != "" { + return true + } + } + + return false +} + +func normalizeSpecs(regions []*mdbv1.AdvancedRegionConfig) { + for _, region := range regions { + if region == nil { + return + } + + var notNilSpecs mdbv1.Specs + if region.ElectableSpecs != nil { + notNilSpecs = *region.ElectableSpecs + } else if region.ReadOnlySpecs != nil { + notNilSpecs = *region.ReadOnlySpecs + } else if region.AnalyticsSpecs != nil { + notNilSpecs = *region.AnalyticsSpecs + } + + if region.ElectableSpecs == nil { + region.ElectableSpecs = ¬NilSpecs + region.ElectableSpecs.NodeCount = toptr.MakePtr(0) + } + + if region.ReadOnlySpecs == nil { + region.ReadOnlySpecs = ¬NilSpecs + region.ReadOnlySpecs.NodeCount = toptr.MakePtr(0) + } + + if region.AnalyticsSpecs == nil { + region.AnalyticsSpecs = ¬NilSpecs + region.AnalyticsSpecs.NodeCount = toptr.MakePtr(0) + } + } +} diff --git a/pkg/controller/atlasdeployment/region_configuration_test.go b/pkg/controller/atlasdeployment/region_configuration_test.go new file mode 100644 index 0000000000..09d8778bfe --- /dev/null +++ b/pkg/controller/atlasdeployment/region_configuration_test.go @@ -0,0 +1,981 @@ +package atlasdeployment + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "go.mongodb.org/atlas/mongodbatlas" + + mdbv1 "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1" + "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/toptr" +) + +func TestSyncComputeConfiguration(t *testing.T) { + t.Run("should not modify new region when there's no cluster in Atlas", func(t *testing.T) { + advancedDeployment := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(20), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + expected := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(20), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + + syncRegionConfiguration(advancedDeployment, nil) + assert.Equal(t, expected, advancedDeployment) + }) + + t.Run("should not modify new region without autoscaling", func(t *testing.T) { + advancedDeployment := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(20), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + expected := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(20), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + atlasCluster := &mongodbatlas.AdvancedCluster{ + ReplicationSpecs: []*mongodbatlas.AdvancedReplicationSpec{ + { + RegionConfigs: []*mongodbatlas.AdvancedRegionConfig{ + { + RegionName: "EU_WEST2", + }, + }, + }, + }, + } + + syncRegionConfiguration(advancedDeployment, atlasCluster) + assert.Equal(t, expected, advancedDeployment) + }) + + t.Run("should not modify new region with autoscaling", func(t *testing.T) { + advancedDeployment := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(20), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + expected := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(20), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + atlasCluster := &mongodbatlas.AdvancedCluster{ + ReplicationSpecs: []*mongodbatlas.AdvancedReplicationSpec{ + { + RegionConfigs: []*mongodbatlas.AdvancedRegionConfig{ + { + RegionName: "EU_WEST2", + }, + }, + }, + }, + } + + syncRegionConfiguration(advancedDeployment, atlasCluster) + assert.Equal(t, expected, advancedDeployment) + }) + + t.Run("should not modify when removing a region", func(t *testing.T) { + advancedDeployment := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(20), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + expected := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(20), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + atlasCluster := &mongodbatlas.AdvancedCluster{ + ReplicationSpecs: []*mongodbatlas.AdvancedReplicationSpec{ + { + RegionConfigs: []*mongodbatlas.AdvancedRegionConfig{ + { + RegionName: "EU_WEST2", + }, + { + RegionName: "EU_WEST1", + }, + }, + }, + }, + } + + syncRegionConfiguration(advancedDeployment, atlasCluster) + assert.Equal(t, expected, advancedDeployment) + }) + + t.Run("should not modify existing region without autoscaling", func(t *testing.T) { + advancedDeployment := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(20), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + expected := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(20), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + atlasCluster := &mongodbatlas.AdvancedCluster{ + ReplicationSpecs: []*mongodbatlas.AdvancedReplicationSpec{ + { + RegionConfigs: []*mongodbatlas.AdvancedRegionConfig{ + { + RegionName: "EU_WEST2", + }, + }, + }, + }, + } + + syncRegionConfiguration(advancedDeployment, atlasCluster) + assert.Equal(t, expected, advancedDeployment) + }) + + t.Run("should unset instance size for existing region with compute autoscaling enabled", func(t *testing.T) { + advancedDeployment := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(20), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ + Compute: &mdbv1.ComputeSpec{ + Enabled: toptr.MakePtr(true), + ScaleDownEnabled: toptr.MakePtr(true), + MinInstanceSize: "M10", + MaxInstanceSize: "M30", + }, + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + expected := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(20), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + NodeCount: toptr.MakePtr(1), + }, + AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ + Compute: &mdbv1.ComputeSpec{ + Enabled: toptr.MakePtr(true), + ScaleDownEnabled: toptr.MakePtr(true), + MinInstanceSize: "M10", + MaxInstanceSize: "M30", + }, + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + atlasCluster := &mongodbatlas.AdvancedCluster{ + ReplicationSpecs: []*mongodbatlas.AdvancedReplicationSpec{ + { + RegionConfigs: []*mongodbatlas.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mongodbatlas.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mongodbatlas.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mongodbatlas.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AutoScaling: &mongodbatlas.AdvancedAutoScaling{ + Compute: &mongodbatlas.Compute{ + Enabled: toptr.MakePtr(true), + ScaleDownEnabled: toptr.MakePtr(true), + MinInstanceSize: "M10", + MaxInstanceSize: "M30", + }, + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + + syncRegionConfiguration(advancedDeployment, atlasCluster) + assert.Equal(t, expected, advancedDeployment) + }) + + t.Run("should unset compute autoscaling for existing region when it is disabled", func(t *testing.T) { + advancedDeployment := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(20), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ + Compute: &mdbv1.ComputeSpec{ + Enabled: toptr.MakePtr(false), + ScaleDownEnabled: toptr.MakePtr(false), + MinInstanceSize: "M10", + MaxInstanceSize: "M30", + }, + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + expected := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(20), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AutoScaling: &mdbv1.AdvancedAutoScalingSpec{}, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + atlasCluster := &mongodbatlas.AdvancedCluster{ + ReplicationSpecs: []*mongodbatlas.AdvancedReplicationSpec{ + { + RegionConfigs: []*mongodbatlas.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mongodbatlas.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mongodbatlas.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mongodbatlas.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AutoScaling: &mongodbatlas.AdvancedAutoScaling{ + Compute: &mongodbatlas.Compute{ + Enabled: toptr.MakePtr(false), + ScaleDownEnabled: toptr.MakePtr(false), + MinInstanceSize: "M10", + MaxInstanceSize: "M30", + }, + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + + syncRegionConfiguration(advancedDeployment, atlasCluster) + assert.Equal(t, expected, advancedDeployment) + }) + + t.Run("should unset disc size for existing region with disc autoscaling enabled and disk size has not be changed", func(t *testing.T) { + advancedDeployment := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(20), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ + DiskGB: &mdbv1.DiskGB{ + Enabled: toptr.MakePtr(true), + }, + Compute: &mdbv1.ComputeSpec{ + Enabled: toptr.MakePtr(false), + ScaleDownEnabled: toptr.MakePtr(false), + MinInstanceSize: "M10", + MaxInstanceSize: "M30", + }, + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + expected := &mdbv1.AdvancedDeploymentSpec{ + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ + DiskGB: &mdbv1.DiskGB{ + Enabled: toptr.MakePtr(true), + }, + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + atlasCluster := &mongodbatlas.AdvancedCluster{ + DiskSizeGB: toptr.MakePtr(20.0), + ReplicationSpecs: []*mongodbatlas.AdvancedReplicationSpec{ + { + RegionConfigs: []*mongodbatlas.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mongodbatlas.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mongodbatlas.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mongodbatlas.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AutoScaling: &mongodbatlas.AdvancedAutoScaling{ + DiskGB: &mongodbatlas.DiskGB{ + Enabled: toptr.MakePtr(true), + }, + Compute: &mongodbatlas.Compute{ + Enabled: toptr.MakePtr(false), + ScaleDownEnabled: toptr.MakePtr(false), + MinInstanceSize: "M10", + MaxInstanceSize: "M30", + }, + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + + syncRegionConfiguration(advancedDeployment, atlasCluster) + assert.Equal(t, expected, advancedDeployment) + }) + + t.Run("should keep disc size for existing region with disc autoscaling enabled but disk size has be changed", func(t *testing.T) { + advancedDeployment := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(30), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ + DiskGB: &mdbv1.DiskGB{ + Enabled: toptr.MakePtr(true), + }, + Compute: &mdbv1.ComputeSpec{ + Enabled: toptr.MakePtr(false), + ScaleDownEnabled: toptr.MakePtr(false), + MinInstanceSize: "M10", + MaxInstanceSize: "M30", + }, + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + expected := &mdbv1.AdvancedDeploymentSpec{ + DiskSizeGB: toptr.MakePtr(30), + ReplicationSpecs: []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ + DiskGB: &mdbv1.DiskGB{ + Enabled: toptr.MakePtr(true), + }, + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + atlasCluster := &mongodbatlas.AdvancedCluster{ + DiskSizeGB: toptr.MakePtr(20.0), + ReplicationSpecs: []*mongodbatlas.AdvancedReplicationSpec{ + { + RegionConfigs: []*mongodbatlas.AdvancedRegionConfig{ + { + ProviderName: "AWS", + RegionName: "EU_WEST2", + ElectableSpecs: &mongodbatlas.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mongodbatlas.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mongodbatlas.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AutoScaling: &mongodbatlas.AdvancedAutoScaling{ + DiskGB: &mongodbatlas.DiskGB{ + Enabled: toptr.MakePtr(true), + }, + Compute: &mongodbatlas.Compute{ + Enabled: toptr.MakePtr(false), + ScaleDownEnabled: toptr.MakePtr(false), + MinInstanceSize: "M10", + MaxInstanceSize: "M30", + }, + }, + Priority: toptr.MakePtr(7), + }, + }, + }, + }, + } + + syncRegionConfiguration(advancedDeployment, atlasCluster) + assert.Equal(t, expected, advancedDeployment) + }) +} + +func TestNormalizeSpecs(t *testing.T) { + t.Run("should do no action for a nil slice", func(t *testing.T) { + var regions []*mdbv1.AdvancedRegionConfig + normalizeSpecs(regions) + + assert.Nil(t, regions) + }) + + t.Run("should do no action for a nil entry in the slice", func(t *testing.T) { + regions := []*mdbv1.AdvancedRegionConfig{ + nil, + } + normalizeSpecs(regions) + + assert.Equal( + t, + []*mdbv1.AdvancedRegionConfig{ + nil, + }, + regions, + ) + }) + + t.Run("should do no action when all specs are not nil", func(t *testing.T) { + regions := []*mdbv1.AdvancedRegionConfig{ + { + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(2), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + }, + } + expected := []*mdbv1.AdvancedRegionConfig{ + { + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(2), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + }, + } + normalizeSpecs(regions) + + assert.Equal( + t, + expected, + regions, + ) + }) + + t.Run("should use electable spec as base when not nil", func(t *testing.T) { + regions := []*mdbv1.AdvancedRegionConfig{ + { + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + }, + } + expected := []*mdbv1.AdvancedRegionConfig{ + { + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(0), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(0), + }, + }, + } + normalizeSpecs(regions) + + assert.Equal( + t, + expected, + regions, + ) + }) + + t.Run("should use read only spec as base when not nil", func(t *testing.T) { + regions := []*mdbv1.AdvancedRegionConfig{ + { + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + }, + } + expected := []*mdbv1.AdvancedRegionConfig{ + { + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(0), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(0), + }, + }, + } + normalizeSpecs(regions) + + assert.Equal( + t, + expected, + regions, + ) + }) + + t.Run("should use analytics spec as base when not nil", func(t *testing.T) { + regions := []*mdbv1.AdvancedRegionConfig{ + { + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + }, + } + expected := []*mdbv1.AdvancedRegionConfig{ + { + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(0), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(0), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + }, + } + normalizeSpecs(regions) + + assert.Equal( + t, + expected, + regions, + ) + }) + + t.Run("should use read only spec as base when analytics is also not nil", func(t *testing.T) { + regions := []*mdbv1.AdvancedRegionConfig{ + { + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(2), + }, + }, + } + expected := []*mdbv1.AdvancedRegionConfig{ + { + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(0), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(2), + }, + }, + } + normalizeSpecs(regions) + + assert.Equal( + t, + expected, + regions, + ) + }) +} diff --git a/pkg/controller/atlasdeployment/instance_size.go b/pkg/controller/validate/instance_size.go similarity index 86% rename from pkg/controller/atlasdeployment/instance_size.go rename to pkg/controller/validate/instance_size.go index cf0426c20f..76e1f6960f 100644 --- a/pkg/controller/atlasdeployment/instance_size.go +++ b/pkg/controller/validate/instance_size.go @@ -1,4 +1,4 @@ -package atlasdeployment +package validate import ( "errors" @@ -13,6 +13,14 @@ type InstanceSize struct { IsNVME bool } +func (i *InstanceSize) String() string { + if i.IsNVME { + return fmt.Sprintf("%s%d_NVME", i.Family, i.Size) + } + + return fmt.Sprintf("%s%d", i.Family, i.Size) +} + func CompareInstanceSizes(is1 InstanceSize, is2 InstanceSize) int { if is1.Family != is2.Family { if is1.Family == "M" { diff --git a/pkg/controller/atlasdeployment/instance_size_test.go b/pkg/controller/validate/instance_size_test.go similarity index 99% rename from pkg/controller/atlasdeployment/instance_size_test.go rename to pkg/controller/validate/instance_size_test.go index ab6a2cffae..ce7e4e2edb 100644 --- a/pkg/controller/atlasdeployment/instance_size_test.go +++ b/pkg/controller/validate/instance_size_test.go @@ -1,4 +1,4 @@ -package atlasdeployment +package validate import ( "testing" diff --git a/pkg/controller/validate/validate.go b/pkg/controller/validate/validate.go index cad148cf37..e628023c86 100644 --- a/pkg/controller/validate/validate.go +++ b/pkg/controller/validate/validate.go @@ -63,14 +63,19 @@ func DeploymentSpec(deploymentSpec *mdbv1.AtlasDeploymentSpec, isGov bool, regio } if deploymentSpec.AdvancedDeploymentSpec != nil { + autoscalingErr := autoscalingForAdvancedDeployment(deploymentSpec.AdvancedDeploymentSpec.ReplicationSpecs) + if autoscalingErr != nil { + err = errors.Join(err, autoscalingErr) + } + instanceSizeErr := instanceSizeForAdvancedDeployment(deploymentSpec.AdvancedDeploymentSpec.ReplicationSpecs) if instanceSizeErr != nil { err = errors.Join(err, instanceSizeErr) } - autoscalingErr := autoscalingForAdvancedDeployment(deploymentSpec.AdvancedDeploymentSpec.ReplicationSpecs) - if autoscalingErr != nil { - err = errors.Join(err, autoscalingErr) + instanceSizeRangeErr := instanceSizeRangeForAdvancedDeployment(deploymentSpec.AdvancedDeploymentSpec.ReplicationSpecs) + if instanceSizeRangeErr != nil { + err = errors.Join(err, instanceSizeRangeErr) } } @@ -282,32 +287,42 @@ func moreThanOneIsNonNil(values ...interface{}) bool { } func instanceSizeForAdvancedDeployment(replicationSpecs []*mdbv1.AdvancedReplicationSpec) error { - var instanceSize string - err := errors.New("instance size must be the same for all nodes in all regions and across all replication specs for advanced deployment ") + err := errors.New("instance size must be the same for all nodes in all regions and across all replication specs for advanced deployment") + + instanceSize := "" + firstNonEmptySize := func(region *mdbv1.AdvancedRegionConfig) string { + if instanceSize != "" { + return instanceSize + } + + if region.ElectableSpecs != nil && region.ElectableSpecs.InstanceSize != "" { + return region.ElectableSpecs.InstanceSize + } + + if region.ReadOnlySpecs != nil && region.ReadOnlySpecs.InstanceSize != "" { + return region.ReadOnlySpecs.InstanceSize + } - isInstanceSizeEqual := func(nodeInstanceType string) bool { - if instanceSize == "" { - instanceSize = nodeInstanceType + if region.AnalyticsSpecs != nil && region.AnalyticsSpecs.InstanceSize != "" { + return region.AnalyticsSpecs.InstanceSize } - return nodeInstanceType == instanceSize + return "" } for _, replicationSpec := range replicationSpecs { for _, regionSpec := range replicationSpec.RegionConfigs { - if instanceSize == "" { - instanceSize = regionSpec.ElectableSpecs.InstanceSize - } + instanceSize = firstNonEmptySize(regionSpec) - if regionSpec.ElectableSpecs != nil && !isInstanceSizeEqual(regionSpec.ElectableSpecs.InstanceSize) { + if regionSpec.ElectableSpecs != nil && regionSpec.ElectableSpecs.InstanceSize != instanceSize { return err } - if regionSpec.ReadOnlySpecs != nil && !isInstanceSizeEqual(regionSpec.ReadOnlySpecs.InstanceSize) { + if regionSpec.ReadOnlySpecs != nil && regionSpec.ReadOnlySpecs.InstanceSize != instanceSize { return err } - if regionSpec.AnalyticsSpecs != nil && !isInstanceSizeEqual(regionSpec.AnalyticsSpecs.InstanceSize) { + if regionSpec.AnalyticsSpecs != nil && regionSpec.AnalyticsSpecs.InstanceSize != instanceSize { return err } } @@ -316,6 +331,76 @@ func instanceSizeForAdvancedDeployment(replicationSpecs []*mdbv1.AdvancedReplica return nil } +func instanceSizeRangeForAdvancedDeployment(replicationSpecs []*mdbv1.AdvancedReplicationSpec) error { + var err error + for _, replicationSpec := range replicationSpecs { + for _, regionSpec := range replicationSpec.RegionConfigs { + if regionSpec.AutoScaling == nil || regionSpec.AutoScaling.Compute == nil || regionSpec.AutoScaling.Compute.Enabled == nil || !*regionSpec.AutoScaling.Compute.Enabled { + continue + } + + if regionSpec.ElectableSpecs != nil { + if rangeErr := advancedInstanceSizeInRange( + regionSpec.ElectableSpecs.InstanceSize, + regionSpec.AutoScaling.Compute.MinInstanceSize, + regionSpec.AutoScaling.Compute.MaxInstanceSize); rangeErr != nil { + err = errors.Join(err, rangeErr) + continue + } + } + + if regionSpec.ReadOnlySpecs != nil { + if rangeErr := advancedInstanceSizeInRange( + regionSpec.ReadOnlySpecs.InstanceSize, + regionSpec.AutoScaling.Compute.MinInstanceSize, + regionSpec.AutoScaling.Compute.MaxInstanceSize); rangeErr != nil { + err = errors.Join(err, rangeErr) + continue + } + } + + if regionSpec.AnalyticsSpecs != nil { + if rangeErr := advancedInstanceSizeInRange( + regionSpec.AnalyticsSpecs.InstanceSize, + regionSpec.AutoScaling.Compute.MinInstanceSize, + regionSpec.AutoScaling.Compute.MaxInstanceSize); rangeErr != nil { + err = errors.Join(err, rangeErr) + continue + } + } + } + } + + return err +} + +func advancedInstanceSizeInRange(currentInstanceSize, minInstanceSize, maxInstanceSize string) error { + minSize, err := NewFromInstanceSizeName(minInstanceSize) + if err != nil { + return err + } + + maxSize, err := NewFromInstanceSizeName(maxInstanceSize) + if err != nil { + return err + } + + currentSize, err := NewFromInstanceSizeName(currentInstanceSize) + if err != nil { + return err + } + + if CompareInstanceSizes(currentSize, minSize) == -1 { + return errors.New("the instance size is below the minimum autoscaling configuration") + } + + if CompareInstanceSizes(currentSize, maxSize) == 1 { + return errors.New("the instance size is above the maximum autoscaling configuration") + } + + return nil +} + func autoscalingForAdvancedDeployment(replicationSpecs []*mdbv1.AdvancedReplicationSpec) error { var autoscaling *mdbv1.AdvancedAutoScalingSpec first := true @@ -328,7 +413,7 @@ func autoscalingForAdvancedDeployment(replicationSpecs []*mdbv1.AdvancedReplicat } if cmp.Diff(autoscaling, regionSpec.AutoScaling, cmpopts.EquateEmpty()) != "" { - return errors.New("autoscaling must be the same for all regions and across all replication specs for advanced deployment ") + return errors.New("autoscaling must be the same for all regions and across all replication specs for advanced deployment") } } } diff --git a/pkg/controller/validate/validate_test.go b/pkg/controller/validate/validate_test.go index 0dd0cca3f3..2353154e67 100644 --- a/pkg/controller/validate/validate_test.go +++ b/pkg/controller/validate/validate_test.go @@ -976,3 +976,292 @@ func wrapKey(s string) string { func wrappedKey() string { return wrapKey(newPrivateKeyPEM()) } + +func TestInstanceSizeForAdvancedDeployment(t *testing.T) { + t.Run("should succeed when instance size are the same for all node types", func(t *testing.T) { + replicationSpecs := []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(0), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + }, + }, + }, + } + + assert.NoError(t, instanceSizeForAdvancedDeployment(replicationSpecs)) + }) + + t.Run("should fail when instance size are different between node types", func(t *testing.T) { + replicationSpecs := []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(0), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M20", + NodeCount: toptr.MakePtr(1), + }, + }, + }, + }, + } + + assert.EqualError(t, instanceSizeForAdvancedDeployment(replicationSpecs), "instance size must be the same for all nodes in all regions and across all replication specs for advanced deployment") + }) + + t.Run("should fail when instance size are different across regions", func(t *testing.T) { + replicationSpecs := []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(0), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + }, + { + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M20", + NodeCount: toptr.MakePtr(0), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M20", + NodeCount: toptr.MakePtr(1), + }, + }, + }, + }, + } + + assert.EqualError(t, instanceSizeForAdvancedDeployment(replicationSpecs), "instance size must be the same for all nodes in all regions and across all replication specs for advanced deployment") + }) +} + +func TestInstanceSizeRangeForAdvancedDeployment(t *testing.T) { + t.Run("should succeed when region has no autoscaling config", func(t *testing.T) { + replicationSpecs := []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + }, + }, + }, + } + + assert.NoError(t, instanceSizeRangeForAdvancedDeployment(replicationSpecs)) + }) + + t.Run("should succeed when instance size is with autoscaling range", func(t *testing.T) { + replicationSpecs := []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ + Compute: &mdbv1.ComputeSpec{ + Enabled: toptr.MakePtr(true), + ScaleDownEnabled: toptr.MakePtr(true), + MinInstanceSize: "M10", + MaxInstanceSize: "M30", + }, + }, + }, + }, + }, + } + + assert.NoError(t, instanceSizeRangeForAdvancedDeployment(replicationSpecs)) + }) + + t.Run("should fail when instance size is below autoscaling range", func(t *testing.T) { + replicationSpecs := []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M10", + NodeCount: toptr.MakePtr(1), + }, + AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ + Compute: &mdbv1.ComputeSpec{ + Enabled: toptr.MakePtr(true), + ScaleDownEnabled: toptr.MakePtr(true), + MinInstanceSize: "M20", + MaxInstanceSize: "M40", + }, + }, + }, + }, + }, + } + + assert.EqualError(t, instanceSizeRangeForAdvancedDeployment(replicationSpecs), "the instance size is below the minimum autoscaling configuration") + }) + + t.Run("should fail when instance size is above autoscaling range", func(t *testing.T) { + replicationSpecs := []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + ElectableSpecs: &mdbv1.Specs{ + InstanceSize: "M40", + NodeCount: toptr.MakePtr(3), + }, + ReadOnlySpecs: &mdbv1.Specs{ + InstanceSize: "M40", + NodeCount: toptr.MakePtr(1), + }, + AnalyticsSpecs: &mdbv1.Specs{ + InstanceSize: "M40", + NodeCount: toptr.MakePtr(1), + }, + AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ + Compute: &mdbv1.ComputeSpec{ + Enabled: toptr.MakePtr(true), + ScaleDownEnabled: toptr.MakePtr(true), + MinInstanceSize: "M10", + MaxInstanceSize: "M30", + }, + }, + }, + }, + }, + } + + assert.EqualError(t, instanceSizeRangeForAdvancedDeployment(replicationSpecs), "the instance size is above the maximum autoscaling configuration") + }) +} + +func TestAutoscalingForAdvancedDeployment(t *testing.T) { + t.Run("should fail when different compute autoscaling config are set", func(t *testing.T) { + replicationSpecs := []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ + DiskGB: &mdbv1.DiskGB{ + Enabled: toptr.MakePtr(true), + }, + Compute: &mdbv1.ComputeSpec{ + Enabled: toptr.MakePtr(true), + ScaleDownEnabled: toptr.MakePtr(true), + MinInstanceSize: "M10", + MaxInstanceSize: "M40", + }, + }, + }, + { + AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ + DiskGB: &mdbv1.DiskGB{ + Enabled: toptr.MakePtr(true), + }, + Compute: &mdbv1.ComputeSpec{ + Enabled: toptr.MakePtr(true), + ScaleDownEnabled: toptr.MakePtr(false), + MinInstanceSize: "M10", + MaxInstanceSize: "M40", + }, + }, + }, + }, + }, + } + + assert.EqualError(t, autoscalingForAdvancedDeployment(replicationSpecs), "autoscaling must be the same for all regions and across all replication specs for advanced deployment") + }) + + t.Run("should fail when different disc autoscaling config are set", func(t *testing.T) { + replicationSpecs := []*mdbv1.AdvancedReplicationSpec{ + { + RegionConfigs: []*mdbv1.AdvancedRegionConfig{ + { + AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ + DiskGB: &mdbv1.DiskGB{ + Enabled: toptr.MakePtr(false), + }, + Compute: &mdbv1.ComputeSpec{ + Enabled: toptr.MakePtr(true), + ScaleDownEnabled: toptr.MakePtr(true), + MinInstanceSize: "M10", + MaxInstanceSize: "M40", + }, + }, + }, + { + AutoScaling: &mdbv1.AdvancedAutoScalingSpec{ + DiskGB: &mdbv1.DiskGB{ + Enabled: toptr.MakePtr(true), + }, + Compute: &mdbv1.ComputeSpec{ + Enabled: toptr.MakePtr(true), + ScaleDownEnabled: toptr.MakePtr(true), + MinInstanceSize: "M10", + MaxInstanceSize: "M40", + }, + }, + }, + }, + }, + } + + assert.EqualError(t, autoscalingForAdvancedDeployment(replicationSpecs), "autoscaling must be the same for all regions and across all replication specs for advanced deployment") + }) +} diff --git a/test/int/deployment_test.go b/test/int/deployment_test.go index a57768f565..10a85a5018 100644 --- a/test/int/deployment_test.go +++ b/test/int/deployment_test.go @@ -48,8 +48,7 @@ const ( ) const ( - interval = PollingInterval - intervalShort = time.Second * 2 + interval = PollingInterval ) var _ = Describe("AtlasDeployment", Label("int", "AtlasDeployment", "deployment-non-backups"), func() { @@ -468,6 +467,12 @@ var _ = Describe("AtlasDeployment", Label("int", "AtlasDeployment", "deployment- }, DiskGBEnabled: boolptr(false), } + createdDeployment.Spec.DeploymentSpec.ProviderSettings.AutoScaling = &mdbv1.AutoScalingSpec{ + Compute: &mdbv1.ComputeSpec{ + MinInstanceSize: "", + MaxInstanceSize: "", + }, + } performUpdate(DeploymentUpdateTimeout) @@ -835,6 +840,8 @@ var _ = Describe("AtlasDeployment", Label("int", "AtlasDeployment", "deployment- By(fmt.Sprintf("Updating the InstanceSize of Advanced Deployment %s", kube.ObjectKeyFromObject(createdDeployment)), func() { createdDeployment.Spec.AdvancedDeploymentSpec.ReplicationSpecs[0].RegionConfigs[0].ElectableSpecs.InstanceSize = "M20" + createdDeployment.Spec.AdvancedDeploymentSpec.ReplicationSpecs[0].RegionConfigs[0].ReadOnlySpecs.InstanceSize = "M20" + createdDeployment.Spec.AdvancedDeploymentSpec.ReplicationSpecs[0].RegionConfigs[0].AnalyticsSpecs.InstanceSize = "M20" Expect(k8sClient.Update(context.Background(), createdDeployment)).ToNot(HaveOccurred()) Eventually(func(g Gomega) bool { @@ -850,6 +857,8 @@ var _ = Describe("AtlasDeployment", Label("int", "AtlasDeployment", "deployment- By(fmt.Sprintf("Enable AutoScaling for the Advanced Deployment %s", kube.ObjectKeyFromObject(createdDeployment)), func() { regionConfig := createdDeployment.Spec.AdvancedDeploymentSpec.ReplicationSpecs[0].RegionConfigs[0] regionConfig.ElectableSpecs.InstanceSize = "M10" + regionConfig.ReadOnlySpecs.InstanceSize = "M10" + regionConfig.AnalyticsSpecs.InstanceSize = "M10" regionConfig.AutoScaling = &mdbv1.AdvancedAutoScalingSpec{ Compute: &mdbv1.ComputeSpec{ Enabled: toptr.MakePtr(true), @@ -877,6 +886,8 @@ var _ = Describe("AtlasDeployment", Label("int", "AtlasDeployment", "deployment- regionConfig := createdDeployment.Spec.AdvancedDeploymentSpec.ReplicationSpecs[0].RegionConfigs[0] regionConfig.AutoScaling.Compute.MinInstanceSize = "M20" regionConfig.ElectableSpecs.InstanceSize = "M20" + regionConfig.ReadOnlySpecs.InstanceSize = "M20" + regionConfig.AnalyticsSpecs.InstanceSize = "M20" Expect(k8sClient.Update(context.Background(), createdDeployment)).ToNot(HaveOccurred()) Eventually(func(g Gomega) bool { @@ -963,7 +974,7 @@ var _ = Describe("AtlasDeployment", Label("int", "AtlasDeployment", "deployment- k8sClient, createdDeployment, status. - FalseCondition(status.DeploymentReadyType). + FalseCondition(status.ValidationSucceeded). WithReason(string(workflow.Internal)). WithMessageRegexp("instance size is invalid"), ) @@ -978,6 +989,15 @@ var _ = Describe("AtlasDeployment", Label("int", "AtlasDeployment", "deployment- err := compat.JSONCopy(&previousDeployment, createdDeployment) Expect(err).NotTo(HaveOccurred()) + createdDeployment.Spec.AdvancedDeploymentSpec.ReplicationSpecs[0]. + RegionConfigs[0]. + ElectableSpecs.InstanceSize = "M20" + createdDeployment.Spec.AdvancedDeploymentSpec.ReplicationSpecs[0]. + RegionConfigs[0]. + ReadOnlySpecs.InstanceSize = "M20" + createdDeployment.Spec.AdvancedDeploymentSpec.ReplicationSpecs[0]. + RegionConfigs[0]. + AnalyticsSpecs.InstanceSize = "M20" createdDeployment.Spec.AdvancedDeploymentSpec.ReplicationSpecs[0]. RegionConfigs[0]. AutoScaling.