Skip to content

Commit ffb2f08

Browse files
CLOUDP-155410: Fix operator bug with existing m0 cluster (#862)
Co-authored-by: fabritsius <antonfabritsius@gmail.com>
1 parent 6a2c70f commit ffb2f08

File tree

5 files changed

+166
-1
lines changed

5 files changed

+166
-1
lines changed

.github/workflows/test-e2e.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ jobs:
137137
"deployment-ns",
138138
"deployment-wide",
139139
"encryption-at-rest",
140+
"free-tier",
140141
"global-deployment",
141142
"helm-ns",
142143
"helm-update",

pkg/controller/atlasdeployment/advanced_deployment.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import (
1515
"github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/compat"
1616
)
1717

18+
const FreeTier = "M0"
19+
1820
func (r *AtlasDeploymentReconciler) ensureAdvancedDeploymentState(ctx *workflow.Context, project *mdbv1.AtlasProject, deployment *mdbv1.AtlasDeployment) (*mongodbatlas.AdvancedCluster, workflow.Result) {
1921
advancedDeploymentSpec := deployment.Spec.AdvancedDeploymentSpec
2022

@@ -210,12 +212,16 @@ func handleAutoscaling(ctx *workflow.Context, desiredDeployment *mdbv1.AdvancedD
210212

211213
// MergedAdvancedDeployment will return the result of merging AtlasDeploymentSpec with Atlas Advanced Deployment
212214
func MergedAdvancedDeployment(atlasDeploymentAsAtlas mongodbatlas.AdvancedCluster, specDeployment mdbv1.AdvancedDeploymentSpec) (mergedDeployment mdbv1.AdvancedDeploymentSpec, atlasDeployment mdbv1.AdvancedDeploymentSpec, err error) {
215+
if IsFreeTierAdvancedDeployment(&atlasDeploymentAsAtlas) {
216+
atlasDeploymentAsAtlas.DiskSizeGB = nil
217+
}
213218
atlasDeployment, err = AdvancedDeploymentFromAtlas(atlasDeploymentAsAtlas)
214219
if err != nil {
215220
return
216221
}
217222

218223
mergedDeployment = mdbv1.AdvancedDeploymentSpec{}
224+
219225
if err = compat.JSONCopy(&mergedDeployment, atlasDeployment); err != nil {
220226
return
221227
}
@@ -236,6 +242,23 @@ func MergedAdvancedDeployment(atlasDeploymentAsAtlas mongodbatlas.AdvancedCluste
236242
return
237243
}
238244

245+
func IsFreeTierAdvancedDeployment(deployment *mongodbatlas.AdvancedCluster) bool {
246+
if deployment != nil && deployment.ReplicationSpecs != nil {
247+
for _, replicationSpec := range deployment.ReplicationSpecs {
248+
if replicationSpec.RegionConfigs != nil {
249+
for _, regionConfig := range replicationSpec.RegionConfigs {
250+
if regionConfig != nil &&
251+
regionConfig.ElectableSpecs != nil &&
252+
regionConfig.ElectableSpecs.InstanceSize == FreeTier {
253+
return true
254+
}
255+
}
256+
}
257+
}
258+
}
259+
return false
260+
}
261+
239262
func AdvancedDeploymentFromAtlas(advancedDeployment mongodbatlas.AdvancedCluster) (mdbv1.AdvancedDeploymentSpec, error) {
240263
result := mdbv1.AdvancedDeploymentSpec{}
241264
if err := compat.JSONCopy(&result, advancedDeployment); err != nil {

pkg/controller/atlasdeployment/deployment.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,20 @@ func cleanupDeployment(deployment mongodbatlas.Cluster) mongodbatlas.Cluster {
126126
deployment.ReplicationSpec = nil
127127
deployment.ConnectionStrings = nil
128128
deployment = removeOutdatedFields(&deployment, nil)
129+
if IsFreeTierCluster(&deployment) {
130+
deployment.DiskSizeGB = nil
131+
}
129132

130133
return deployment
131134
}
132135

136+
func IsFreeTierCluster(deployment *mongodbatlas.Cluster) bool {
137+
if deployment != nil && deployment.ProviderSettings != nil && deployment.ProviderSettings.InstanceSizeName == "M0" {
138+
return true
139+
}
140+
return false
141+
}
142+
133143
// removeOutdatedFields unsets fields which are should be empty based on flags
134144
func removeOutdatedFields(removeFrom *mongodbatlas.Cluster, lookAt *mongodbatlas.Cluster) mongodbatlas.Cluster {
135145
if lookAt == nil {

test/e2e/data/deployments.go

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const (
1818
InstanceSizeM20 = "M20"
1919
InstanceSizeM30 = "M30"
2020
InstanceSizeM0 = "M0"
21+
AWSRegion = "US_EAST_1"
2122

2223
ServerlessProviderName = "SERVERLESS"
2324
)
@@ -274,7 +275,7 @@ func CreateBasicFreeDeployment(name string) *v1.AtlasDeployment {
274275
Name: ProjectName,
275276
},
276277
DeploymentSpec: &v1.DeploymentSpec{
277-
Name: "cluster-basics-free",
278+
Name: name,
278279
ProviderSettings: &v1.ProviderSettingsSpec{
279280
InstanceSizeName: InstanceSizeM0,
280281
ProviderName: "TENANT",
@@ -285,3 +286,52 @@ func CreateBasicFreeDeployment(name string) *v1.AtlasDeployment {
285286
},
286287
}
287288
}
289+
290+
func CreateFreeAdvancedDeployment(name string) *v1.AtlasDeployment {
291+
return &v1.AtlasDeployment{
292+
ObjectMeta: metav1.ObjectMeta{
293+
Name: name,
294+
},
295+
Spec: v1.AtlasDeploymentSpec{
296+
Project: common.ResourceRefNamespaced{
297+
Name: ProjectName,
298+
},
299+
AdvancedDeploymentSpec: &v1.AdvancedDeploymentSpec{
300+
Name: name,
301+
BackupEnabled: toptr.MakePtr(false),
302+
BiConnector: &v1.BiConnectorSpec{
303+
Enabled: toptr.MakePtr(false),
304+
ReadPreference: "secondary",
305+
},
306+
ClusterType: string(v1.TypeReplicaSet),
307+
EncryptionAtRestProvider: "NONE",
308+
PitEnabled: toptr.MakePtr(false),
309+
Paused: toptr.MakePtr(false),
310+
RootCertType: "ISRGROOTX1",
311+
VersionReleaseSystem: "LTS",
312+
ReplicationSpecs: []*v1.AdvancedReplicationSpec{
313+
{
314+
NumShards: 1,
315+
ZoneName: "Zone 1",
316+
RegionConfigs: []*v1.AdvancedRegionConfig{
317+
{
318+
ElectableSpecs: &v1.Specs{
319+
InstanceSize: InstanceSizeM0,
320+
},
321+
Priority: toptr.MakePtr(7),
322+
ProviderName: string(provider.ProviderTenant),
323+
BackingProviderName: string(provider.ProviderAWS),
324+
RegionName: AWSRegion,
325+
},
326+
},
327+
},
328+
},
329+
},
330+
ProcessArgs: &v1.ProcessArgs{
331+
JavascriptEnabled: toptr.MakePtr(true),
332+
MinimumEnabledTLSProtocol: "TLS1_2",
333+
NoTableScan: toptr.MakePtr(false),
334+
},
335+
},
336+
}
337+
}

test/e2e/free_tier_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package e2e_test
2+
3+
import (
4+
. "github.com/onsi/ginkgo/v2"
5+
. "github.com/onsi/gomega"
6+
"go.mongodb.org/atlas/mongodbatlas"
7+
8+
"github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1/provider"
9+
"github.com/mongodb/mongodb-atlas-kubernetes/test/e2e/actions"
10+
"github.com/mongodb/mongodb-atlas-kubernetes/test/e2e/actions/deploy"
11+
"github.com/mongodb/mongodb-atlas-kubernetes/test/e2e/api/atlas"
12+
"github.com/mongodb/mongodb-atlas-kubernetes/test/e2e/data"
13+
"github.com/mongodb/mongodb-atlas-kubernetes/test/e2e/model"
14+
)
15+
16+
var _ = Describe("Free tier", Label("free-tier"), func() {
17+
var testData *model.TestDataProvider
18+
19+
_ = AfterEach(func() {
20+
GinkgoWriter.Write([]byte("\n"))
21+
GinkgoWriter.Write([]byte("===============================================\n"))
22+
GinkgoWriter.Write([]byte("Free tier test\n"))
23+
GinkgoWriter.Write([]byte("Operator namespace: " + testData.Resources.Namespace + "\n"))
24+
GinkgoWriter.Write([]byte("===============================================\n"))
25+
if CurrentSpecReport().Failed() {
26+
Expect(actions.SaveProjectsToFile(testData.Context, testData.K8SClient, testData.Resources.Namespace)).Should(Succeed())
27+
Expect(actions.SaveDeploymentsToFile(testData.Context, testData.K8SClient, testData.Resources.Namespace)).Should(Succeed())
28+
}
29+
By("Delete Resources", func() {
30+
actions.DeleteTestDataDeployments(testData)
31+
actions.DeleteTestDataProject(testData)
32+
actions.AfterEachFinalCleanup([]model.TestDataProvider{*testData})
33+
})
34+
})
35+
36+
DescribeTable("Operator should support exported CR for free tier deployments",
37+
func(test *model.TestDataProvider) {
38+
testData = test
39+
actions.ProjectCreationFlow(test)
40+
freeTierDeploymentFlow(test)
41+
},
42+
Entry("Test free tier deployment",
43+
model.DataProvider(
44+
"free-tier",
45+
model.NewEmptyAtlasKeyType().UseDefaultFullAccess(),
46+
40000,
47+
[]func(*model.TestDataProvider){},
48+
).WithProject(data.DefaultProject()).WithInitialDeployments(data.CreateBasicFreeDeployment("free-tier")),
49+
),
50+
Entry("Test free tier advanced deployment",
51+
model.DataProvider(
52+
"free-tier-advanced",
53+
model.NewEmptyAtlasKeyType().UseDefaultFullAccess(),
54+
40000,
55+
[]func(*model.TestDataProvider){},
56+
).WithProject(data.DefaultProject()).WithInitialDeployments(data.CreateFreeAdvancedDeployment("free-tier")),
57+
),
58+
)
59+
})
60+
61+
func freeTierDeploymentFlow(userData *model.TestDataProvider) {
62+
By("Create free cluster in Atlas", func() {
63+
aClient := atlas.GetClientOrFail()
64+
Expect(userData.InitialDeployments).Should(HaveLen(1))
65+
name := userData.InitialDeployments[0].GetDeploymentName()
66+
_, _, err := aClient.Client.Clusters.Create(userData.Context, userData.Project.ID(), &mongodbatlas.Cluster{
67+
Name: name,
68+
ProviderSettings: &mongodbatlas.ProviderSettings{
69+
ProviderName: string(provider.ProviderTenant),
70+
RegionName: "US_EAST_1",
71+
InstanceSizeName: data.InstanceSizeM0,
72+
BackingProviderName: string(provider.ProviderAWS),
73+
},
74+
})
75+
Expect(err).ShouldNot(HaveOccurred())
76+
})
77+
78+
By("Apply deployment CR", func() {
79+
deploy.CreateInitialDeployments(userData)
80+
})
81+
}

0 commit comments

Comments
 (0)