Skip to content

Commit 9f8e617

Browse files
authored
CLOUDP-296922: test/int/project: fix conflicting kube updates (#2095)
* test/int/project: fix conflicting kube updates * fix nil panic
1 parent 3ea89a2 commit 9f8e617

File tree

1 file changed

+57
-51
lines changed

1 file changed

+57
-51
lines changed

test/int/project_test.go

Lines changed: 57 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/events"
2929
"github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/maintenance"
3030
"github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/resources"
31+
akoretry "github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/retry"
3132
)
3233

3334
const (
@@ -348,15 +349,18 @@ var _ = Describe("AtlasProject", Label("int", "AtlasProject"), func() {
348349
// Updating (the existing project is expected to be read from Atlas)
349350
By("Updating the project")
350351

351-
createdProject.Spec.ProjectIPAccessList = []project.IPAccessList{{CIDRBlock: "0.0.0.0/0"}}
352-
createdProject.Spec.MaintenanceWindow = project.MaintenanceWindow{
353-
DayOfWeek: 4,
354-
HourOfDay: 11,
355-
AutoDefer: true,
356-
StartASAP: false,
357-
Defer: false,
358-
}
359-
Expect(k8sClient.Update(context.Background(), createdProject)).To(Succeed())
352+
var err error
353+
createdProject, err = akoretry.RetryUpdateOnConflict(context.Background(), k8sClient, client.ObjectKeyFromObject(createdProject), func(p *akov2.AtlasProject) {
354+
p.Spec.ProjectIPAccessList = []project.IPAccessList{{CIDRBlock: "0.0.0.0/0"}}
355+
p.Spec.MaintenanceWindow = project.MaintenanceWindow{
356+
DayOfWeek: 4,
357+
HourOfDay: 11,
358+
AutoDefer: true,
359+
StartASAP: false,
360+
Defer: false,
361+
}
362+
})
363+
Expect(err).To(BeNil())
360364

361365
Eventually(func() bool {
362366
return resources.CheckCondition(k8sClient, createdProject, api.TrueCondition(api.ReadyType))
@@ -392,16 +396,21 @@ var _ = Describe("AtlasProject", Label("int", "AtlasProject"), func() {
392396
})
393397
By("Breaking the Connection Secret", func() {
394398
connectionSecret = buildConnectionSecret("my-atlas-key")
395-
connectionSecret.StringData["publicApiKey"] = "non-existing"
396-
Expect(k8sClient.Update(context.Background(), &connectionSecret)).To(Succeed())
397-
398-
Eventually(updateK8sObject[*akov2.AtlasProject](createdProject, func(createdProject *akov2.AtlasProject) {
399-
createdProject.Spec.AlertConfigurationSyncEnabled = true
400-
})).WithPolling(interval).WithTimeout(20 * time.Second).Should(BeTrue())
401-
402-
Eventually(updateK8sObject[*akov2.AtlasProject](secondProject, func(secondProject *akov2.AtlasProject) {
403-
secondProject.Spec.AlertConfigurationSyncEnabled = true
404-
})).WithPolling(interval).WithTimeout(20 * time.Second).Should(BeTrue())
399+
_, err := akoretry.RetryUpdateOnConflict(context.Background(), k8sClient, client.ObjectKeyFromObject(&connectionSecret), func(s *corev1.Secret) {
400+
s.StringData = buildConnectionSecret("my-atlas-key").StringData
401+
s.StringData["publicApiKey"] = "non-existing"
402+
})
403+
Expect(err).To(BeNil())
404+
405+
createdProject, err = akoretry.RetryUpdateOnConflict(context.Background(), k8sClient, client.ObjectKeyFromObject(createdProject), func(p *akov2.AtlasProject) {
406+
p.Spec.AlertConfigurationSyncEnabled = true
407+
})
408+
Expect(err).To(BeNil())
409+
410+
secondProject, err = akoretry.RetryUpdateOnConflict(context.Background(), k8sClient, client.ObjectKeyFromObject(secondProject), func(p *akov2.AtlasProject) {
411+
p.Spec.AlertConfigurationSyncEnabled = true
412+
})
413+
Expect(err).To(BeNil())
405414

406415
// Both projects are expected to get to Failed state right away
407416
expectedCondition := api.FalseCondition(api.ProjectReadyType).WithReason(string(workflow.ProjectNotCreatedInAtlas))
@@ -414,7 +423,10 @@ var _ = Describe("AtlasProject", Label("int", "AtlasProject"), func() {
414423
})
415424
By("Fixing the Connection Secret", func() {
416425
connectionSecret = buildConnectionSecret("my-atlas-key")
417-
Expect(k8sClient.Update(context.Background(), &connectionSecret)).To(Succeed())
426+
_, err := akoretry.RetryUpdateOnConflict(context.Background(), k8sClient, client.ObjectKeyFromObject(&connectionSecret), func(s *corev1.Secret) {
427+
s.StringData = buildConnectionSecret("my-atlas-key").StringData
428+
})
429+
Expect(err).To(BeNil())
418430

419431
// Both projects are expected to recover
420432
Eventually(func() bool {
@@ -529,9 +541,12 @@ var _ = Describe("AtlasProject", Label("int", "AtlasProject"), func() {
529541
})
530542
By("Updating the IP Access List comment and delete date", func() {
531543
// Just a note: Atlas doesn't allow to make the "permanent" entity "temporary". But it works the other way
532-
createdProject.Spec.ProjectIPAccessList[0].Comment = "new comment"
533-
createdProject.Spec.ProjectIPAccessList[0].DeleteAfterDate = ""
534-
Expect(k8sClient.Update(context.Background(), createdProject)).To(Succeed())
544+
var err error
545+
createdProject, err = akoretry.RetryUpdateOnConflict(context.Background(), k8sClient, client.ObjectKeyFromObject(createdProject), func(p *akov2.AtlasProject) {
546+
p.Spec.ProjectIPAccessList[0].Comment = "new comment"
547+
p.Spec.ProjectIPAccessList[0].DeleteAfterDate = ""
548+
})
549+
Expect(err).To(BeNil())
535550

536551
Eventually(func(g Gomega) bool {
537552
return resources.CheckCondition(k8sClient, createdProject, api.TrueCondition(api.ReadyType), validateNoErrorsIPAccessListDuringUpdate(g))
@@ -558,11 +573,14 @@ var _ = Describe("AtlasProject", Label("int", "AtlasProject"), func() {
558573
})
559574
By("Updating the IP Access List IPAddress", func() {
560575
twoDaysLater := time.Now().Add(time.Hour * 48).Format("2006-01-02T15:04:05Z")
561-
createdProject.Spec.ProjectIPAccessList[0].DeleteAfterDate = twoDaysLater
562-
// Update of the IP address will result in delete for the old IP address first and then the new
563-
// IP address will be created
564-
createdProject.Spec.ProjectIPAccessList[1].IPAddress = "168.32.54.0"
565-
Expect(k8sClient.Update(context.Background(), createdProject)).To(Succeed())
576+
var err error
577+
createdProject, err = akoretry.RetryUpdateOnConflict(context.Background(), k8sClient, client.ObjectKeyFromObject(createdProject), func(p *akov2.AtlasProject) {
578+
p.Spec.ProjectIPAccessList[0].DeleteAfterDate = twoDaysLater
579+
// Update of the IP address will result in delete for the old IP address first and then the new
580+
// IP address will be created
581+
p.Spec.ProjectIPAccessList[1].IPAddress = "168.32.54.0"
582+
})
583+
Expect(err).To(BeNil())
566584

567585
Eventually(func(g Gomega) bool {
568586
return resources.CheckCondition(k8sClient, createdProject, api.TrueCondition(api.ReadyType), validateNoErrorsIPAccessListDuringUpdate(g))
@@ -594,9 +612,12 @@ var _ = Describe("AtlasProject", Label("int", "AtlasProject"), func() {
594612

595613
})
596614
By("Updating the project maintenance window hour and enabling auto-defer", func() {
597-
createdProject.Spec.MaintenanceWindow.HourOfDay = 3
598-
createdProject.Spec.MaintenanceWindow.AutoDefer = true
599-
Expect(k8sClient.Update(context.Background(), createdProject)).To(Succeed())
615+
var err error
616+
createdProject, err = akoretry.RetryUpdateOnConflict(context.Background(), k8sClient, client.ObjectKeyFromObject(createdProject), func(p *akov2.AtlasProject) {
617+
p.Spec.MaintenanceWindow.HourOfDay = 3
618+
p.Spec.MaintenanceWindow.AutoDefer = true
619+
})
620+
Expect(err).To(BeNil())
600621

601622
Eventually(func(g Gomega) bool {
602623
return resources.CheckCondition(k8sClient, createdProject, api.TrueCondition(api.ReadyType), validateNoErrorsMaintenanceWindowDuringUpdate(g))
@@ -608,8 +629,11 @@ var _ = Describe("AtlasProject", Label("int", "AtlasProject"), func() {
608629
checkMaintenanceWindowInAtlas()
609630
})
610631
By("Toggling auto-defer to false", func() {
611-
createdProject.Spec.MaintenanceWindow.AutoDefer = false
612-
Expect(k8sClient.Update(context.Background(), createdProject)).To(Succeed())
632+
var err error
633+
createdProject, err = akoretry.RetryUpdateOnConflict(context.Background(), k8sClient, client.ObjectKeyFromObject(createdProject), func(p *akov2.AtlasProject) {
634+
p.Spec.MaintenanceWindow.AutoDefer = false
635+
})
636+
Expect(err).To(BeNil())
613637

614638
Eventually(func(g Gomega) bool {
615639
return resources.CheckCondition(k8sClient, createdProject, api.TrueCondition(api.ReadyType), validateNoErrorsMaintenanceWindowDuringUpdate(g))
@@ -762,21 +786,3 @@ func deleteK8sObject(obj client.Object) func() bool {
762786
return true
763787
}
764788
}
765-
766-
func updateK8sObject[T client.Object](obj T, updateFn func(T)) func() bool {
767-
return func() bool {
768-
nn := kube.ObjectKeyFromObject(obj)
769-
GinkgoWriter.Printf("Updating %s/%s\n", nn.Namespace, nn.Name)
770-
err := k8sClient.Get(context.Background(), nn, obj)
771-
if err == nil {
772-
updateFn(obj)
773-
err = k8sClient.Update(context.Background(), obj)
774-
}
775-
if err != nil {
776-
GinkgoWriter.Printf("Failed to update %s/%s: %v\n", nn.Namespace, nn.Name, err)
777-
return false
778-
}
779-
GinkgoWriter.Printf("Updated %s/%s\n", nn.Namespace, nn.Name)
780-
return true
781-
}
782-
}

0 commit comments

Comments
 (0)