Skip to content

Commit

Permalink
fix(NfsBackupSchedule): continuous looping of the one-time schedule (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ravi-shankar-sap authored Nov 21, 2024
1 parent b9ddfc8 commit 2373497
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ var _ = Describe("Feature: SKR AwsNfsBackupSchedule", func() {
WithArguments(
infra.Ctx(), infra.SKR().Client(), nfsBackupSchedule,
NewObjActions(),
HaveNextRunTimes(expectedTimes),
HaveLastCreateRun(expectedTimes[0]),
).
Should(Succeed())
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ var _ = Describe("Feature: SKR GcpNfsBackupSchedule", func() {
WithArguments(
infra.Ctx(), infra.SKR().Client(), nfsBackupSchedule,
NewObjActions(),
HaveNextRunTimes(expectedTimes),
HaveLastCreateRun(expectedTimes[0]),
).
Should(Succeed())
})
Expand Down
16 changes: 15 additions & 1 deletion pkg/skr/backupschedule/calculateOnetimeSchedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,22 @@ func calculateOnetimeSchedule(ctx context.Context, st composed.State) (error, co

logger.WithValues("BackupSchedule", schedule.GetName()).Info("BackupSchedule is empty and scheduling it to run.")

//Set the next run time to the start time if it is set
var nextRunTime time.Time
lastCreateRun := schedule.GetLastCreateRun()

//If an adhoc backup is already created,
//Run the schedule once a day to check for backup retention.
if schedule.GetBackupCount() > 0 && !lastCreateRun.IsZero() {
nextRunTime = time.Date(now.Year(), now.Month(), now.Day()+1,
lastCreateRun.Hour()+1, 0, 0, 0, time.UTC)
schedule.SetNextRunTimes([]string{nextRunTime.UTC().Format(time.RFC3339)})

return composed.PatchStatus(schedule).
SuccessError(composed.StopWithRequeue).
Run(ctx, state)
}

//Set the next run time to the start time if it is set
if schedule.GetStartTime() != nil && !schedule.GetStartTime().IsZero() {
nextRunTime = schedule.GetStartTime().Time
} else {
Expand Down
40 changes: 40 additions & 0 deletions pkg/skr/backupschedule/calculateOnetimeSchedule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,46 @@ func (suite *calculateOnetimeScheduleSuite) TestScheduleWithNoStartTime() {
suite.GreaterOrEqual(time.Second*1, time.Since(runTime))
}

func (suite *calculateOnetimeScheduleSuite) TestScheduleWithLastCreateRun() {

obj := gcpNfsBackupSchedule.DeepCopy()
factory, err := newTestStateFactoryWithObj(obj)
suite.Nil(err)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

//Get state object with GcpNfsBackupSchedule
state, err := factory.newStateWith(obj)
suite.Nil(err)

//Set the schedule
lastCreateRun := &metav1.Time{Time: time.Now()}
obj.Status.LastCreateRun = lastCreateRun
obj.Status.BackupCount = 1
err = factory.skrCluster.K8sClient().Status().Update(ctx, obj)
suite.Nil(err)

//Invoke API under test
err, _ = calculateOnetimeSchedule(ctx, state)

//validate expected return values
suite.Equal(composed.StopWithRequeue, err)

fromK8s := &v1beta1.GcpNfsBackupSchedule{}
err = factory.skrCluster.K8sClient().Get(ctx,
types.NamespacedName{Name: gcpNfsBackupSchedule.Name,
Namespace: gcpNfsBackupSchedule.Namespace},
fromK8s)
suite.Nil(err)
suite.Equal(1, len(fromK8s.Status.NextRunTimes))
expectedNextRun := time.Date(lastCreateRun.Year(), lastCreateRun.Month(), lastCreateRun.Day()+1,
lastCreateRun.Hour()+1, 0, 0, 0, time.UTC)
runTime, err := time.Parse(time.RFC3339, fromK8s.Status.NextRunTimes[0])
suite.Nil(err)
suite.Equal(expectedNextRun, runTime)
}

func TestCalculateOnetimeScheduleSuite(t *testing.T) {
suite.Run(t, new(calculateOnetimeScheduleSuite))
}
5 changes: 5 additions & 0 deletions pkg/skr/backupschedule/evaluateNextRun.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ func evaluateNextRun(ctx context.Context, st composed.State) (error, context.Con
state.createRunCompleted = schedule.GetLastCreateRun() != nil && nextRunTime.Equal(schedule.GetLastCreateRun().Time)
state.deleteRunCompleted = schedule.GetLastDeleteRun() != nil && nextRunTime.Equal(schedule.GetLastDeleteRun().Time)

//Mark createRunCompleted to true always after first run for one-time schedules.
if schedule.GetSchedule() == "" && schedule.GetLastCreateRun() != nil && !schedule.GetLastCreateRun().IsZero() {
state.createRunCompleted = true
}

//If create and delete tasks already completed for currentRun, reset the next run times
if state.createRunCompleted && state.deleteRunCompleted {

Expand Down
25 changes: 13 additions & 12 deletions pkg/testinfra/dsl/nfsBackupSchedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,18 +141,19 @@ func HaveNextRunTimes(expectedTimes []time.Time) ObjAssertion {
}
}

func WithNextRunTime(runTime time.Time) ObjStatusAction {
return &objStatusAction{
f: func(obj client.Object) {
if x, ok := obj.(backupschedule.BackupSchedule); ok {
nextRunTimes := x.GetNextRunTimes()
t := runTime.UTC().Format(time.RFC3339)
if len(nextRunTimes) == 0 {
x.SetNextRunTimes([]string{t})
} else {
nextRunTimes[0] = t
}
func HaveLastCreateRun(expected time.Time) ObjAssertion {
return func(obj client.Object) error {
if x, ok := obj.(backupschedule.BackupSchedule); ok {
actual := x.GetLastCreateRun()

if actual.IsZero() || actual.Time.UTC() != expected.UTC() {
return fmt.Errorf(
"expected object %T %s/%s to have lastCreateRun: %s, but found %s",
obj, obj.GetNamespace(), obj.GetName(), expected, actual,
)
}
},

}
return nil
}
}

0 comments on commit 2373497

Please sign in to comment.