diff --git a/internal/health/condition/check_backup_ready.go b/internal/health/condition/check_backup_ready.go index 6906e401b..24f8bf35d 100644 --- a/internal/health/condition/check_backup_ready.go +++ b/internal/health/condition/check_backup_ready.go @@ -42,6 +42,7 @@ const ( NotChecked string = "NotChecked" ) +// BackupReadyCheck returns a result for the "BackupReady" condition check func BackupReadyCheck(results []Result) Result { result := &result{ conType: druidv1alpha1.ConditionTypeBackupReady, @@ -52,6 +53,9 @@ func BackupReadyCheck(results []Result) Result { var FullSnapshotBackupReadyCheckResult, DeltaSnapshotBackupReadyCheckResult Result = nil, nil for _, result := range results { + if result == nil { + continue + } if result.ConditionType() == druidv1alpha1.ConditionTypeFullSnapshotBackupReady { FullSnapshotBackupReadyCheckResult = result continue diff --git a/internal/health/condition/check_backup_ready_test.go b/internal/health/condition/check_backup_ready_test.go index 5684a0c20..786d1c63f 100644 --- a/internal/health/condition/check_backup_ready_test.go +++ b/internal/health/condition/check_backup_ready_test.go @@ -25,387 +25,389 @@ import ( ) var _ = Describe("BackupsReadyCheck", func() { - var ( - storageProvider druidv1alpha1.StorageProvider = "testStorageProvider" - mockCtrl *gomock.Controller - cl *mockclient.MockClient - holderIDString = "123455" - noLeaseError = apierrors.StatusError{ - ErrStatus: v1.Status{ - Reason: v1.StatusReasonNotFound, - }, - } - deltaSnapshotDuration = 2 * time.Minute - - etcd = druidv1alpha1.Etcd{ - ObjectMeta: v1.ObjectMeta{ - Name: "test-etcd", - Namespace: "default", - }, - Spec: druidv1alpha1.EtcdSpec{ - Replicas: 1, - Backup: druidv1alpha1.BackupSpec{ - DeltaSnapshotPeriod: &v1.Duration{ - Duration: deltaSnapshotDuration, - }, - Store: &druidv1alpha1.StoreSpec{ - Prefix: "test-prefix", - Provider: &storageProvider, + Describe("#SnapshotsBackupReadyCheck", func() { + var ( + storageProvider druidv1alpha1.StorageProvider = "testStorageProvider" + mockCtrl *gomock.Controller + cl *mockclient.MockClient + holderIDString = "123455" + noLeaseError = apierrors.StatusError{ + ErrStatus: v1.Status{ + Reason: v1.StatusReasonNotFound, + }, + } + deltaSnapshotDuration = 2 * time.Minute + + etcd = druidv1alpha1.Etcd{ + ObjectMeta: v1.ObjectMeta{ + Name: "test-etcd", + Namespace: "default", + }, + Spec: druidv1alpha1.EtcdSpec{ + Replicas: 1, + Backup: druidv1alpha1.BackupSpec{ + DeltaSnapshotPeriod: &v1.Duration{ + Duration: deltaSnapshotDuration, + }, + Store: &druidv1alpha1.StoreSpec{ + Prefix: "test-prefix", + Provider: &storageProvider, + }, }, }, - }, - Status: druidv1alpha1.EtcdStatus{}, - } - lease = coordinationv1.Lease{ - ObjectMeta: v1.ObjectMeta{ - Name: "test-etcd-snap", - }, - Spec: coordinationv1.LeaseSpec{ - HolderIdentity: &holderIDString, - RenewTime: &v1.MicroTime{ - Time: time.Now(), + Status: druidv1alpha1.EtcdStatus{}, + } + lease = coordinationv1.Lease{ + ObjectMeta: v1.ObjectMeta{ + Name: "test-etcd-snap", }, - }, - } - ) - - BeforeEach(func() { - mockCtrl = gomock.NewController(GinkgoT()) - cl = mockclient.NewMockClient(mockCtrl) - }) - - AfterEach(func() { - mockCtrl.Finish() - }) - Describe("#DeltaSnapshotBackupReadyCheck", func() { - - Context("With no delta snapshot lease present", func() { - It("Should return Unknown readiness", func() { - cl.EXPECT().Get(context.TODO(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, er *coordinationv1.Lease, _ ...client.GetOption) error { - return &noLeaseError + Spec: coordinationv1.LeaseSpec{ + HolderIdentity: &holderIDString, + RenewTime: &v1.MicroTime{ + Time: time.Now(), }, - ).AnyTimes() + }, + } + ) - check := DeltaSnapshotBackupReadyCheck(cl) - result := check.Check(context.TODO(), etcd) - Expect(result).ToNot(BeNil()) - Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady)) - Expect(result.Status()).To(Equal(druidv1alpha1.ConditionUnknown)) - Expect(result.Reason()).To(Equal(Unknown)) - }) + BeforeEach(func() { + mockCtrl = gomock.NewController(GinkgoT()) + cl = mockclient.NewMockClient(mockCtrl) }) - Context("With delta snapshot lease present", func() { - - Context("With lease not renewed even once", func() { - It("Should set status to True if lease has not been renewed within the deltaSnapshotPeriod duration of lease creation", func() { - cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-delta-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { - *le = lease - le.Spec.RenewTime = nil - le.Spec.HolderIdentity = nil - le.ObjectMeta.CreationTimestamp = v1.Now() - return nil - }, - ).AnyTimes() - - check := DeltaSnapshotBackupReadyCheck(cl) - result := check.Check(context.TODO(), etcd) - - Expect(result).ToNot(BeNil()) - Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady)) - Expect(result.Status()).To(Equal(druidv1alpha1.ConditionTrue)) - Expect(result.Reason()).To(Equal(SnapshotProcessNotStarted)) - }) + AfterEach(func() { + mockCtrl.Finish() + }) + Describe("#DeltaSnapshotBackupReadyCheck", func() { - It("Should set status to Unknown if lease has not been renewed until 3*deltaSnapshotPeriod duration of lease creation", func() { - cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-delta-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { - *le = lease - le.Spec.RenewTime = nil - le.Spec.HolderIdentity = nil - le.ObjectMeta.CreationTimestamp = v1.Time{Time: time.Now().Add(-2 * deltaSnapshotDuration)} - return nil + Context("With no delta snapshot lease present", func() { + It("Should return Unknown readiness", func() { + cl.EXPECT().Get(context.TODO(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, er *coordinationv1.Lease, _ ...client.GetOption) error { + return &noLeaseError }, ).AnyTimes() check := DeltaSnapshotBackupReadyCheck(cl) result := check.Check(context.TODO(), etcd) - Expect(result).ToNot(BeNil()) Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady)) Expect(result.Status()).To(Equal(druidv1alpha1.ConditionUnknown)) Expect(result.Reason()).To(Equal(Unknown)) }) - - It("Should set status to False if lease has not been renewed even after 3*deltaSnapshotPeriod duration of lease creation", func() { - cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-delta-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { - *le = lease - le.Spec.RenewTime = nil - le.Spec.HolderIdentity = nil - le.ObjectMeta.CreationTimestamp = v1.Time{Time: time.Now().Add(-4 * deltaSnapshotDuration)} - return nil - }, - ).AnyTimes() - - etcd.Status.Conditions = []druidv1alpha1.Condition{ - { - Type: druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady, - Status: druidv1alpha1.ConditionUnknown, - Message: "Unknown", - }, - } - - check := DeltaSnapshotBackupReadyCheck(cl) - result := check.Check(context.TODO(), etcd) - - Expect(result).ToNot(BeNil()) - Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady)) - Expect(result.Status()).To(Equal(druidv1alpha1.ConditionFalse)) - Expect(result.Reason()).To(Equal(SnapshotMissedSchedule)) - }) }) - Context("With lease renewed at least once", func() { - It("Should set status to True if lease has been renewed within the deltaSnapshotPeriod duration", func() { - cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-delta-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { - *le = lease - le.Spec.RenewTime = &v1.MicroTime{Time: time.Now()} - return nil - }, - ).AnyTimes() - - check := DeltaSnapshotBackupReadyCheck(cl) - result := check.Check(context.TODO(), etcd) + Context("With delta snapshot lease present", func() { + + Context("With lease not renewed even once", func() { + It("Should set status to True if lease has not been renewed within the deltaSnapshotPeriod duration of lease creation", func() { + cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-delta-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { + *le = lease + le.Spec.RenewTime = nil + le.Spec.HolderIdentity = nil + le.ObjectMeta.CreationTimestamp = v1.Now() + return nil + }, + ).AnyTimes() + + check := DeltaSnapshotBackupReadyCheck(cl) + result := check.Check(context.TODO(), etcd) + + Expect(result).ToNot(BeNil()) + Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady)) + Expect(result.Status()).To(Equal(druidv1alpha1.ConditionTrue)) + Expect(result.Reason()).To(Equal(SnapshotProcessNotStarted)) + }) + + It("Should set status to Unknown if lease has not been renewed until 3*deltaSnapshotPeriod duration of lease creation", func() { + cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-delta-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { + *le = lease + le.Spec.RenewTime = nil + le.Spec.HolderIdentity = nil + le.ObjectMeta.CreationTimestamp = v1.Time{Time: time.Now().Add(-2 * deltaSnapshotDuration)} + return nil + }, + ).AnyTimes() + + check := DeltaSnapshotBackupReadyCheck(cl) + result := check.Check(context.TODO(), etcd) + + Expect(result).ToNot(BeNil()) + Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady)) + Expect(result.Status()).To(Equal(druidv1alpha1.ConditionUnknown)) + Expect(result.Reason()).To(Equal(Unknown)) + }) + + It("Should set status to False if lease has not been renewed even after 3*deltaSnapshotPeriod duration of lease creation", func() { + cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-delta-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { + *le = lease + le.Spec.RenewTime = nil + le.Spec.HolderIdentity = nil + le.ObjectMeta.CreationTimestamp = v1.Time{Time: time.Now().Add(-4 * deltaSnapshotDuration)} + return nil + }, + ).AnyTimes() + + etcd.Status.Conditions = []druidv1alpha1.Condition{ + { + Type: druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady, + Status: druidv1alpha1.ConditionUnknown, + Message: "Unknown", + }, + } + + check := DeltaSnapshotBackupReadyCheck(cl) + result := check.Check(context.TODO(), etcd) + + Expect(result).ToNot(BeNil()) + Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady)) + Expect(result.Status()).To(Equal(druidv1alpha1.ConditionFalse)) + Expect(result.Reason()).To(Equal(SnapshotMissedSchedule)) + }) + }) - Expect(result).ToNot(BeNil()) - Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady)) - Expect(result.Status()).To(Equal(druidv1alpha1.ConditionTrue)) - Expect(result.Reason()).To(Equal(SnapshotUploadedOnSchedule)) + Context("With lease renewed at least once", func() { + It("Should set status to True if lease has been renewed within the deltaSnapshotPeriod duration", func() { + cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-delta-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { + *le = lease + le.Spec.RenewTime = &v1.MicroTime{Time: time.Now()} + return nil + }, + ).AnyTimes() + + check := DeltaSnapshotBackupReadyCheck(cl) + result := check.Check(context.TODO(), etcd) + + Expect(result).ToNot(BeNil()) + Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady)) + Expect(result.Status()).To(Equal(druidv1alpha1.ConditionTrue)) + Expect(result.Reason()).To(Equal(SnapshotUploadedOnSchedule)) + }) + + It("Should set status to Unknown if lease has not been renewed within the 3*deltaSnapshotPeriod duration", func() { + cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-delta-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { + *le = lease + le.Spec.RenewTime = &v1.MicroTime{Time: time.Now().Add(-2 * deltaSnapshotDuration)} + return nil + }, + ).AnyTimes() + + check := DeltaSnapshotBackupReadyCheck(cl) + result := check.Check(context.TODO(), etcd) + + Expect(result).ToNot(BeNil()) + Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady)) + Expect(result.Status()).To(Equal(druidv1alpha1.ConditionUnknown)) + Expect(result.Reason()).To(Equal(Unknown)) + }) + + It("Should set status to False if lease has not been renewed even after 3*deltaSnapshotPeriod duration", func() { + cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-delta-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { + *le = lease + le.Spec.RenewTime = &v1.MicroTime{Time: time.Now().Add(-4 * deltaSnapshotDuration)} + return nil + }, + ).AnyTimes() + + etcd.Status.Conditions = []druidv1alpha1.Condition{ + { + Type: druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady, + Status: druidv1alpha1.ConditionUnknown, + Message: "Unknown", + }, + } + + check := DeltaSnapshotBackupReadyCheck(cl) + result := check.Check(context.TODO(), etcd) + + Expect(result).ToNot(BeNil()) + Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady)) + Expect(result.Status()).To(Equal(druidv1alpha1.ConditionFalse)) + Expect(result.Reason()).To(Equal(SnapshotMissedSchedule)) + }) }) + }) - It("Should set status to Unknown if lease has not been renewed within the 3*deltaSnapshotPeriod duration", func() { - cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-delta-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { - *le = lease - le.Spec.RenewTime = &v1.MicroTime{Time: time.Now().Add(-2 * deltaSnapshotDuration)} - return nil + Context("With no backup store configured", func() { + It("Should return nil condition", func() { + cl.EXPECT().Get(context.TODO(), gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, er *coordinationv1.Lease) error { + return &noLeaseError }, ).AnyTimes() + etcd.Spec.Backup.Store = nil check := DeltaSnapshotBackupReadyCheck(cl) result := check.Check(context.TODO(), etcd) - Expect(result).ToNot(BeNil()) - Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady)) - Expect(result.Status()).To(Equal(druidv1alpha1.ConditionUnknown)) - Expect(result.Reason()).To(Equal(Unknown)) + Expect(result).To(BeNil()) + etcd.Spec.Backup.Store = &druidv1alpha1.StoreSpec{ + Prefix: "test-prefix", + Provider: &storageProvider, + } }) + }) - It("Should set status to False if lease has not been renewed even after 3*deltaSnapshotPeriod duration", func() { - cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-delta-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { - *le = lease - le.Spec.RenewTime = &v1.MicroTime{Time: time.Now().Add(-4 * deltaSnapshotDuration)} - return nil + Context("With backup store is configured but provider is nil", func() { + It("Should return nil condition", func() { + cl.EXPECT().Get(context.TODO(), gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, er *coordinationv1.Lease) error { + return &noLeaseError }, ).AnyTimes() - etcd.Status.Conditions = []druidv1alpha1.Condition{ - { - Type: druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady, - Status: druidv1alpha1.ConditionUnknown, - Message: "Unknown", - }, - } - + etcd.Spec.Backup.Store.Provider = nil check := DeltaSnapshotBackupReadyCheck(cl) result := check.Check(context.TODO(), etcd) - Expect(result).ToNot(BeNil()) - Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady)) - Expect(result.Status()).To(Equal(druidv1alpha1.ConditionFalse)) - Expect(result.Reason()).To(Equal(SnapshotMissedSchedule)) + Expect(result).To(BeNil()) + etcd.Spec.Backup.Store.Provider = &storageProvider }) }) }) - - Context("With no backup store configured", func() { - It("Should return nil condition", func() { - cl.EXPECT().Get(context.TODO(), gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, er *coordinationv1.Lease) error { - return &noLeaseError - }, - ).AnyTimes() - - etcd.Spec.Backup.Store = nil - check := DeltaSnapshotBackupReadyCheck(cl) - result := check.Check(context.TODO(), etcd) - - Expect(result).To(BeNil()) - etcd.Spec.Backup.Store = &druidv1alpha1.StoreSpec{ - Prefix: "test-prefix", - Provider: &storageProvider, - } - }) - }) - - Context("With backup store is configured but provider is nil", func() { - It("Should return nil condition", func() { - cl.EXPECT().Get(context.TODO(), gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, er *coordinationv1.Lease) error { - return &noLeaseError - }, - ).AnyTimes() - - etcd.Spec.Backup.Store.Provider = nil - check := DeltaSnapshotBackupReadyCheck(cl) - result := check.Check(context.TODO(), etcd) - - Expect(result).To(BeNil()) - etcd.Spec.Backup.Store.Provider = &storageProvider - }) - }) - }) - Describe("#FullSnapshotBackupReadyCheck", func() { - Context("With no full snapshot lease present", func() { - It("Should return Unknown readiness", func() { - cl.EXPECT().Get(context.TODO(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, er *coordinationv1.Lease, _ ...client.GetOption) error { - return &noLeaseError - }, - ).AnyTimes() - - check := FullSnapshotBackupReadyCheck(cl) - result := check.Check(context.TODO(), etcd) - Expect(result).ToNot(BeNil()) - Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeFullSnapshotBackupReady)) - Expect(result.Status()).To(Equal(druidv1alpha1.ConditionUnknown)) - Expect(result.Reason()).To(Equal(Unknown)) - }) - }) - - Context("With full snapshot lease present", func() { - Context("With lease not renewed even once", func() { - It("Should set status to Unknown if lease has not been renewed at all within the first 24 hours of lease creation", func() { - cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-full-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { - *le = lease - le.Spec.RenewTime = nil - le.Spec.HolderIdentity = nil - le.ObjectMeta.CreationTimestamp = v1.Now() - return nil + Describe("#FullSnapshotBackupReadyCheck", func() { + Context("With no full snapshot lease present", func() { + It("Should return Unknown readiness", func() { + cl.EXPECT().Get(context.TODO(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, er *coordinationv1.Lease, _ ...client.GetOption) error { + return &noLeaseError }, ).AnyTimes() check := FullSnapshotBackupReadyCheck(cl) result := check.Check(context.TODO(), etcd) - Expect(result).ToNot(BeNil()) Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeFullSnapshotBackupReady)) Expect(result.Status()).To(Equal(druidv1alpha1.ConditionUnknown)) Expect(result.Reason()).To(Equal(Unknown)) }) + }) - It("Should set status to False if lease has not been renewed at all even after 24 hours of lease creation", func() { - cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-full-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { - *le = lease - le.Spec.RenewTime = nil - le.Spec.HolderIdentity = nil - le.ObjectMeta.CreationTimestamp = v1.Time{Time: time.Now().Add(-25 * time.Hour)} - return nil - }, - ).AnyTimes() - - check := FullSnapshotBackupReadyCheck(cl) - result := check.Check(context.TODO(), etcd) + Context("With full snapshot lease present", func() { + Context("With lease not renewed even once", func() { + It("Should set status to Unknown if lease has not been renewed at all within the first 24 hours of lease creation", func() { + cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-full-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { + *le = lease + le.Spec.RenewTime = nil + le.Spec.HolderIdentity = nil + le.ObjectMeta.CreationTimestamp = v1.Now() + return nil + }, + ).AnyTimes() + + check := FullSnapshotBackupReadyCheck(cl) + result := check.Check(context.TODO(), etcd) + + Expect(result).ToNot(BeNil()) + Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeFullSnapshotBackupReady)) + Expect(result.Status()).To(Equal(druidv1alpha1.ConditionUnknown)) + Expect(result.Reason()).To(Equal(Unknown)) + }) + + It("Should set status to False if lease has not been renewed at all even after 24 hours of lease creation", func() { + cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-full-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { + *le = lease + le.Spec.RenewTime = nil + le.Spec.HolderIdentity = nil + le.ObjectMeta.CreationTimestamp = v1.Time{Time: time.Now().Add(-25 * time.Hour)} + return nil + }, + ).AnyTimes() + + check := FullSnapshotBackupReadyCheck(cl) + result := check.Check(context.TODO(), etcd) + + Expect(result).ToNot(BeNil()) + Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeFullSnapshotBackupReady)) + Expect(result.Status()).To(Equal(druidv1alpha1.ConditionFalse)) + Expect(result.Reason()).To(Equal(SnapshotMissedSchedule)) + }) + }) - Expect(result).ToNot(BeNil()) - Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeFullSnapshotBackupReady)) - Expect(result.Status()).To(Equal(druidv1alpha1.ConditionFalse)) - Expect(result.Reason()).To(Equal(SnapshotMissedSchedule)) + Context("With lease renewed at least once", func() { + It("Should set status to True if lease has been renewed within the last 24 hours", func() { + cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-full-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { + *le = lease + le.Spec.RenewTime = &v1.MicroTime{Time: time.Now()} + return nil + }, + ).AnyTimes() + + check := FullSnapshotBackupReadyCheck(cl) + result := check.Check(context.TODO(), etcd) + + Expect(result).ToNot(BeNil()) + Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeFullSnapshotBackupReady)) + Expect(result.Status()).To(Equal(druidv1alpha1.ConditionTrue)) + Expect(result.Reason()).To(Equal(SnapshotUploadedOnSchedule)) + }) + + It("Should set status to False if lease has not been renewed within the last 24 hours", func() { + cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-full-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { + *le = lease + le.Spec.RenewTime = &v1.MicroTime{Time: time.Now().Add(-25 * time.Hour)} + return nil + }, + ).AnyTimes() + + check := FullSnapshotBackupReadyCheck(cl) + result := check.Check(context.TODO(), etcd) + + Expect(result).ToNot(BeNil()) + Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeFullSnapshotBackupReady)) + Expect(result.Status()).To(Equal(druidv1alpha1.ConditionFalse)) + Expect(result.Reason()).To(Equal(SnapshotMissedSchedule)) + }) }) }) - Context("With lease renewed at least once", func() { - It("Should set status to True if lease has been renewed within the last 24 hours", func() { - cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-full-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { - *le = lease - le.Spec.RenewTime = &v1.MicroTime{Time: time.Now()} - return nil + Context("With no backup store configured", func() { + It("Should return nil condition", func() { + cl.EXPECT().Get(context.TODO(), gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, er *coordinationv1.Lease) error { + return &noLeaseError }, ).AnyTimes() + etcd.Spec.Backup.Store = nil check := FullSnapshotBackupReadyCheck(cl) result := check.Check(context.TODO(), etcd) - Expect(result).ToNot(BeNil()) - Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeFullSnapshotBackupReady)) - Expect(result.Status()).To(Equal(druidv1alpha1.ConditionTrue)) - Expect(result.Reason()).To(Equal(SnapshotUploadedOnSchedule)) + Expect(result).To(BeNil()) + etcd.Spec.Backup.Store = &druidv1alpha1.StoreSpec{ + Prefix: "test-prefix", + Provider: &storageProvider, + } }) + }) - It("Should set status to False if lease has not been renewed within the last 24 hours", func() { - cl.EXPECT().Get(context.TODO(), types.NamespacedName{Name: "test-etcd-full-snap", Namespace: "default"}, gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, le *coordinationv1.Lease, _ ...client.GetOption) error { - *le = lease - le.Spec.RenewTime = &v1.MicroTime{Time: time.Now().Add(-25 * time.Hour)} - return nil + Context("With backup store is configured but provider is nil", func() { + It("Should return nil condition", func() { + cl.EXPECT().Get(context.TODO(), gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, _ client.ObjectKey, er *coordinationv1.Lease) error { + return &noLeaseError }, ).AnyTimes() + etcd.Spec.Backup.Store.Provider = nil check := FullSnapshotBackupReadyCheck(cl) result := check.Check(context.TODO(), etcd) - Expect(result).ToNot(BeNil()) - Expect(result.ConditionType()).To(Equal(druidv1alpha1.ConditionTypeFullSnapshotBackupReady)) - Expect(result.Status()).To(Equal(druidv1alpha1.ConditionFalse)) - Expect(result.Reason()).To(Equal(SnapshotMissedSchedule)) + Expect(result).To(BeNil()) + etcd.Spec.Backup.Store.Provider = &storageProvider }) }) }) - - Context("With no backup store configured", func() { - It("Should return nil condition", func() { - cl.EXPECT().Get(context.TODO(), gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, er *coordinationv1.Lease) error { - return &noLeaseError - }, - ).AnyTimes() - - etcd.Spec.Backup.Store = nil - check := FullSnapshotBackupReadyCheck(cl) - result := check.Check(context.TODO(), etcd) - - Expect(result).To(BeNil()) - etcd.Spec.Backup.Store = &druidv1alpha1.StoreSpec{ - Prefix: "test-prefix", - Provider: &storageProvider, - } - }) - }) - - Context("With backup store is configured but provider is nil", func() { - It("Should return nil condition", func() { - cl.EXPECT().Get(context.TODO(), gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, er *coordinationv1.Lease) error { - return &noLeaseError - }, - ).AnyTimes() - - etcd.Spec.Backup.Store.Provider = nil - check := FullSnapshotBackupReadyCheck(cl) - result := check.Check(context.TODO(), etcd) - - Expect(result).To(BeNil()) - etcd.Spec.Backup.Store.Provider = &storageProvider - }) - }) }) Describe("#BackupReadyCheck", func() { var results []Result @@ -419,10 +421,7 @@ var _ = Describe("BackupsReadyCheck", func() { ConType: druidv1alpha1.ConditionTypeDeltaSnapshotBackupReady, ConStatus: druidv1alpha1.ConditionTrue, }, - &result{ - ConType: druidv1alpha1.ConditionTypeAllMembersReady, - ConStatus: druidv1alpha1.ConditionTrue, - }, + nil, &result{ ConType: druidv1alpha1.ConditionTypeReady, ConStatus: druidv1alpha1.ConditionTrue,