Skip to content

Commit e260eff

Browse files
committed
Fixup
Signed-off-by: Anatolii Bazko <abazko@redhat.com>
1 parent e6f9ede commit e260eff

2 files changed

Lines changed: 48 additions & 97 deletions

File tree

controllers/backupcronjob/backupcronjob_controller.go

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -276,36 +276,39 @@ func (r *BackupCronJobReconciler) executeBackupSync(ctx context.Context, dwOpera
276276
// It reads the last backup time from the DevWorkspace annotation, or falls back to the
277277
// provided globalLastBackupTime if the annotation doesn't exist.
278278
func (r *BackupCronJobReconciler) wasStoppedSinceLastBackup(
279-
workspace *dw.DevWorkspace,
279+
devWorkspace *dw.DevWorkspace,
280280
globalLastBackupTime *metav1.Time,
281281
log logr.Logger,
282282
) bool {
283-
if workspace.Status.Phase != dw.DevWorkspaceStatusStopped {
283+
if devWorkspace.Status.Phase != dw.DevWorkspaceStatusStopped {
284284
return false
285285
}
286-
log.Info("DevWorkspace is currently stopped, checking if it was stopped since last backup", "namespace", workspace.Namespace, "name", workspace.Name)
286+
log.Info("DevWorkspace is currently stopped, checking if it was stopped since last backup", "namespace", devWorkspace.Namespace, "name", devWorkspace.Name)
287287

288-
// Get the last backup time and success status from the workspace annotations
289-
var lastBackupTime *metav1.Time
288+
var lastBackupFinishedAt *metav1.Time
290289
var lastBackupSuccessful bool
291-
if workspace.Annotations != nil {
292-
if lastBackupTimeStr, ok := workspace.Annotations[constants.DevWorkspaceLastBackupFinishedAtAnnotation]; ok {
293-
parsedTime, err := time.Parse(time.RFC3339Nano, lastBackupTimeStr)
290+
291+
// Get the last backup time and success status from the workspace annotations
292+
if devWorkspace.Annotations != nil {
293+
if lastBackupFinishedAtStr, ok := devWorkspace.Annotations[constants.DevWorkspaceLastBackupFinishedAtAnnotation]; ok {
294+
parsedTime, err := time.Parse(time.RFC3339Nano, lastBackupFinishedAtStr)
294295
if err != nil {
295-
log.Error(err, "Failed to parse last backup time annotation, treating as no previous backup", "value", lastBackupTimeStr)
296+
log.Error(err, "Failed to parse last backup time annotation, treating as no previous backup", "value", lastBackupFinishedAtStr)
296297
} else {
297-
lastBackupTime = &metav1.Time{Time: parsedTime}
298+
lastBackupFinishedAt = &metav1.Time{Time: parsedTime}
298299
}
299300
}
300301

301-
lastBackupSuccessful = workspace.Annotations[constants.DevWorkspaceLastBackupSuccessfulAnnotation] == "true"
302-
} else {
302+
lastBackupSuccessful = devWorkspace.Annotations[constants.DevWorkspaceLastBackupSuccessfulAnnotation] == "true"
303+
}
304+
305+
if lastBackupFinishedAt == nil {
303306
// Fall back to globalLastBackupTime if annotation doesn't exist
304-
lastBackupTime = globalLastBackupTime
307+
lastBackupFinishedAt = globalLastBackupTime
305308
lastBackupSuccessful = true
306309
}
307310

308-
if lastBackupTime == nil {
311+
if lastBackupFinishedAt == nil {
309312
return true
310313
}
311314

@@ -314,17 +317,17 @@ func (r *BackupCronJobReconciler) wasStoppedSinceLastBackup(
314317
}
315318

316319
// Check if the workspace was stopped since the last successful backup
317-
if workspace.Status.Conditions != nil {
320+
if devWorkspace.Status.Conditions != nil {
318321
lastTimeStopped := metav1.Time{}
319-
for _, condition := range workspace.Status.Conditions {
322+
for _, condition := range devWorkspace.Status.Conditions {
320323
if condition.Type == conditions.Started && condition.Status == corev1.ConditionFalse {
321324
lastTimeStopped = condition.LastTransitionTime
322325
}
323326
}
324327

325328
if !lastTimeStopped.IsZero() {
326-
if lastTimeStopped.Time.After(lastBackupTime.Time) {
327-
log.Info("DevWorkspace was stopped since last successful backup", "namespace", workspace.Namespace, "name", workspace.Name)
329+
if lastTimeStopped.Time.After(lastBackupFinishedAt.Time) {
330+
log.Info("DevWorkspace was stopped since last successful backup", "namespace", devWorkspace.Namespace, "name", devWorkspace.Name)
328331
return true
329332
}
330333
}

controllers/backupcronjob/backupcronjob_controller_test.go

Lines changed: 27 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -751,85 +751,6 @@ var _ = Describe("BackupCronJobReconciler", func() {
751751
})
752752
})
753753

754-
Context("copySecret", func() {
755-
It("creates a new secret in workspace namespace", func() {
756-
dw := createDevWorkspace("dw-copy-secret", "ns-copy-secret", false, metav1.NewTime(time.Now().Add(-10*time.Minute)))
757-
dw.Status.DevWorkspaceId = "id-copy-secret"
758-
Expect(fakeClient.Create(ctx, dw)).To(Succeed())
759-
760-
sourceSecret := &corev1.Secret{
761-
ObjectMeta: metav1.ObjectMeta{
762-
Name: "source-secret",
763-
Namespace: nameNamespace.Namespace,
764-
},
765-
Data: map[string][]byte{
766-
".dockerconfigjson": []byte(`{"auths":{"registry.example.com":{"auth":"dGVzdDp0ZXN0"}}}`),
767-
},
768-
Type: corev1.SecretTypeDockerConfigJson,
769-
}
770-
771-
copiedSecret, err := reconciler.copySecret(ctx, dw, sourceSecret, log)
772-
Expect(err).ToNot(HaveOccurred())
773-
Expect(copiedSecret).ToNot(BeNil())
774-
Expect(copiedSecret.Name).To(Equal(constants.DevWorkspaceBackupAuthSecretName))
775-
Expect(copiedSecret.Namespace).To(Equal(dw.Namespace))
776-
Expect(copiedSecret.Data).To(Equal(sourceSecret.Data))
777-
Expect(copiedSecret.Type).To(Equal(sourceSecret.Type))
778-
Expect(copiedSecret.Labels).To(HaveKeyWithValue(constants.DevWorkspaceIDLabel, dw.Status.DevWorkspaceId))
779-
Expect(copiedSecret.Labels).To(HaveKeyWithValue(constants.DevWorkspaceWatchSecretLabel, "true"))
780-
781-
// Verify the secret was actually created
782-
createdSecret := &corev1.Secret{}
783-
err = fakeClient.Get(ctx, types.NamespacedName{
784-
Name: constants.DevWorkspaceBackupAuthSecretName,
785-
Namespace: dw.Namespace,
786-
}, createdSecret)
787-
Expect(err).ToNot(HaveOccurred())
788-
})
789-
790-
It("deletes existing secret before creating new one", func() {
791-
dw := createDevWorkspace("dw-replace-secret", "ns-replace-secret", false, metav1.NewTime(time.Now().Add(-10*time.Minute)))
792-
dw.Status.DevWorkspaceId = "id-replace-secret"
793-
Expect(fakeClient.Create(ctx, dw)).To(Succeed())
794-
795-
// Create an existing secret
796-
existingSecret := &corev1.Secret{
797-
ObjectMeta: metav1.ObjectMeta{
798-
Name: constants.DevWorkspaceBackupAuthSecretName,
799-
Namespace: dw.Namespace,
800-
},
801-
Data: map[string][]byte{
802-
".dockerconfigjson": []byte(`{"old":"data"}`),
803-
},
804-
Type: corev1.SecretTypeDockerConfigJson,
805-
}
806-
Expect(fakeClient.Create(ctx, existingSecret)).To(Succeed())
807-
808-
sourceSecret := &corev1.Secret{
809-
ObjectMeta: metav1.ObjectMeta{
810-
Name: "new-source-secret",
811-
Namespace: nameNamespace.Namespace,
812-
},
813-
Data: map[string][]byte{
814-
".dockerconfigjson": []byte(`{"new":"data"}`),
815-
},
816-
Type: corev1.SecretTypeDockerConfigJson,
817-
}
818-
819-
copiedSecret, err := reconciler.copySecret(ctx, dw, sourceSecret, log)
820-
Expect(err).ToNot(HaveOccurred())
821-
Expect(copiedSecret.Data).To(Equal(sourceSecret.Data))
822-
823-
// Verify the secret has the new data
824-
updatedSecret := &corev1.Secret{}
825-
err = fakeClient.Get(ctx, types.NamespacedName{
826-
Name: constants.DevWorkspaceBackupAuthSecretName,
827-
Namespace: dw.Namespace,
828-
}, updatedSecret)
829-
Expect(err).ToNot(HaveOccurred())
830-
Expect(updatedSecret.Data).To(Equal(sourceSecret.Data))
831-
})
832-
})
833754
Context("wasStoppedSinceLastBackup", func() {
834755
It("returns true if DevWorkspace was stopped since last backup", func() {
835756
lastBackupTime := metav1.NewTime(time.Now().Add(-30 * time.Minute))
@@ -934,6 +855,20 @@ var _ = Describe("BackupCronJobReconciler", func() {
934855
Expect(result).To(BeTrue())
935856
})
936857

858+
It("falls back to global last backup time when annotations is empty", func() {
859+
globalLastBackupTime := metav1.NewTime(time.Now().Add(-20 * time.Minute))
860+
workspaceStoppedTime := metav1.NewTime(time.Now().Add(-10 * time.Minute))
861+
862+
dw := createDevWorkspace("dw-test-empty-annotations", "ns-test-empty-annotations", false, workspaceStoppedTime)
863+
// Explicitly ensure annotations is empty
864+
dw.Annotations = map[string]string{}
865+
866+
// With global time (-20min), workspace stopped at -10min, should return true
867+
// lastBackupSuccessful should be treated as true when falling back
868+
result := reconciler.wasStoppedSinceLastBackup(dw, &globalLastBackupTime, log)
869+
Expect(result).To(BeTrue())
870+
})
871+
937872
It("returns false when annotations are nil and workspace stopped before global backup time", func() {
938873
globalLastBackupTime := metav1.NewTime(time.Now().Add(-5 * time.Minute))
939874
workspaceStoppedTime := metav1.NewTime(time.Now().Add(-10 * time.Minute))
@@ -946,6 +881,19 @@ var _ = Describe("BackupCronJobReconciler", func() {
946881
result := reconciler.wasStoppedSinceLastBackup(dw, &globalLastBackupTime, log)
947882
Expect(result).To(BeFalse())
948883
})
884+
885+
It("returns false when annotations is empty and workspace stopped before global backup time", func() {
886+
globalLastBackupTime := metav1.NewTime(time.Now().Add(-5 * time.Minute))
887+
workspaceStoppedTime := metav1.NewTime(time.Now().Add(-10 * time.Minute))
888+
889+
dw := createDevWorkspace("dw-test-empty-old-stop", "ns-test-empty-old-stop", false, workspaceStoppedTime)
890+
// Explicitly ensure annotations is empty
891+
dw.Annotations = map[string]string{}
892+
893+
// With global time (-5min), workspace stopped at -10min, should return false
894+
result := reconciler.wasStoppedSinceLastBackup(dw, &globalLastBackupTime, log)
895+
Expect(result).To(BeFalse())
896+
})
949897
})
950898

951899
})

0 commit comments

Comments
 (0)