Skip to content

Commit

Permalink
refactored implementation to use interface
Browse files Browse the repository at this point in the history
  • Loading branch information
ravi-shankar-sap committed Jul 26, 2024
1 parent bfb2bfe commit ae6a8df
Show file tree
Hide file tree
Showing 31 changed files with 1,138 additions and 312 deletions.
3 changes: 3 additions & 0 deletions api/cloud-resources/v1beta1/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,7 @@ const (
ReasonNfsVolumeNotReady = "NfsVolumeNotReady"
ReasonBackupCreateFailed = "BackupCreateFailed"
ReasonBackupListFailed = "BackupListFailed"
ReasonUnknownSchedule = "UnknownSchedule"
ReasonInvalidStartTime = "InvalidStartTime"
ReasonInvalidEndTime = "InvalidEndTime"
)
14 changes: 11 additions & 3 deletions api/cloud-resources/v1beta1/gcpnfsbackupschedule_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
featuretypes "github.com/kyma-project/cloud-manager/pkg/feature/types"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
Expand Down Expand Up @@ -61,6 +60,8 @@ type GcpNfsBackupScheduleSpec struct {

// MaxRetentionDays specifies the maximum number of days to retain the backup
// If not provided, backup will be retained indefinitely
// If the DeleteCascade is true for this schedule,
// then all the backups will be deleted when the schedule is deleted irrespective of the MaxRetentionDay configuration.
// +optional
MaxRetentionDays int `json:"maxRetentionDays,omitempty"`

Expand Down Expand Up @@ -118,6 +119,10 @@ type GcpNfsBackupScheduleStatus struct {
// BackupIndex specifies the current index of the backup created by this schedule
// +kubebuilder:default=0
BackupIndex int `json:"backupIndex,omitempty"`

//BackupCount specifies the number of backups currently present in the system
// +kubebuilder:default=0
BackupCount int `json:"backupCount,omitempty"`
}

//+kubebuilder:object:root=true
Expand Down Expand Up @@ -256,8 +261,11 @@ func (sc *GcpNfsBackupSchedule) GetBackupIndex() int {
func (sc *GcpNfsBackupSchedule) SetBackupIndex(index int) {
sc.Status.BackupIndex = index
}
func (sc *GcpNfsBackupSchedule) GetList() client.ObjectList {
return &GcpNfsBackupScheduleList{}
func (sc *GcpNfsBackupSchedule) GetBackupCount() int {
return sc.Status.BackupCount
}
func (sc *GcpNfsBackupSchedule) SetBackupCount(count int) {
sc.Status.BackupCount = count
}

//+kubebuilder:object:root=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ spec:
maxRetentionDays:
description: MaxRetentionDays specifies the maximum number of days
to retain the backup If not provided, backup will be retained indefinitely
If the DeleteCascade is true for this schedule, then all the backups
will be deleted when the schedule is deleted irrespective of the
MaxRetentionDay configuration.
type: integer
nfsVolumeRef:
description: NfsVolumeRef specifies the SourceRef resource that a
Expand Down Expand Up @@ -128,6 +131,11 @@ spec:
description: GcpNfsBackupScheduleStatus defines the observed state of
GcpNfsBackupSchedule
properties:
backupCount:
default: 0
description: BackupCount specifies the number of backups currently
present in the system
type: integer
backupIndex:
default: 0
description: BackupIndex specifies the current index of the backup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ spec:
maxRetentionDays:
description: MaxRetentionDays specifies the maximum number of days
to retain the backup If not provided, backup will be retained indefinitely
If the DeleteCascade is true for this schedule, then all the backups
will be deleted when the schedule is deleted irrespective of the
MaxRetentionDay configuration.
type: integer
nfsVolumeRef:
description: NfsVolumeRef specifies the SourceRef resource that a
Expand Down Expand Up @@ -128,6 +131,11 @@ spec:
description: GcpNfsBackupScheduleStatus defines the observed state of
GcpNfsBackupSchedule
properties:
backupCount:
default: 0
description: BackupCount specifies the number of backups currently
present in the system
type: integer
backupIndex:
default: 0
description: BackupIndex specifies the current index of the backup
Expand Down
25 changes: 10 additions & 15 deletions internal/controller/cloud-resources/gcpnfsbackupschedule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ var _ = Describe("Feature: SKR GcpNfsBackupSchedule", func() {

//Define variables.
nfsBackupSchedule := &cloudresourcesv1beta1.GcpNfsBackupSchedule{}
nfsBackupScheduleName := "nfs-backupschedule-1"
nfsBackupScheduleName := "nfs-backup-schedule-1"
nfsBackupHourlySchedule := "0 * * * *"
nfsBackupLocation := "us-west1"

Expand Down Expand Up @@ -196,13 +196,14 @@ var _ = Describe("Feature: SKR GcpNfsBackupSchedule", func() {
Describe("Scenario: SKR Onetime GcpNfsBackupSchedule - Create", func() {
//Define variables.
nfsBackupSchedule := &cloudresourcesv1beta1.GcpNfsBackupSchedule{}
nfsBackupScheduleName := "nfs-backupschedule-2"
nfsBackupScheduleName := "nfs-backup-schedule-2"
nfsBackupLocation := "us-west1"

now := time.Now().UTC()
expectedTimes := []time.Time{now}
start := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute()+2, 0, 0, now.Location()).UTC()
expectedTimes := []time.Time{start}

nfsBackupName := fmt.Sprintf("%s-%d-%s", nfsBackupScheduleName, 1, now.Format("20060102-150405"))
nfsBackupName := fmt.Sprintf("%s-%d-%s", nfsBackupScheduleName, 1, start.Format("20060102-150405"))
nfsBackup := &cloudresourcesv1beta1.GcpNfsVolumeBackup{}

It("When GcpNfsBackupSchedule Create is called", func() {
Expand All @@ -211,19 +212,12 @@ var _ = Describe("Feature: SKR GcpNfsBackupSchedule", func() {
infra.Ctx(), infra.SKR().Client(), nfsBackupSchedule,
WithName(nfsBackupScheduleName),
WithLocation(nfsBackupLocation),
WithStartTime(now),
WithStartTime(start),
WithNfsVolumeRef(skrNfsVolumeName),
).
Should(Succeed())
By("Then GcpNfsBackupSchedule is created in SKR", func() {
Eventually(LoadAndCheck).
WithArguments(
infra.Ctx(), infra.SKR().Client(), nfsBackupSchedule,
NewObjActions(),
).
Should(Succeed())
})
By("And Then GcpNfsBackupSchedule will get NextRun time", func() {

By("Then GcpNfsBackupSchedule will be created in SKR and will have NextRun time", func() {
Eventually(LoadAndCheck).
WithArguments(
infra.Ctx(), infra.SKR().Client(), nfsBackupSchedule,
Expand All @@ -238,7 +232,8 @@ var _ = Describe("Feature: SKR GcpNfsBackupSchedule", func() {

By("Then the NfsVolumeBackup is created", func() {
//Load and check whether the NfsVolumeBackup object got created.
Eventually(LoadAndCheck).
//Waiting little longer as the scheduled backup creation might take about 2 minutes.
Eventually(LoadAndCheck, timeout*6, interval).
WithArguments(
infra.Ctx(), infra.SKR().Client(), nfsBackup,
NewObjActions(WithName(nfsBackupName)),
Expand Down
57 changes: 57 additions & 0 deletions pkg/skr/backupschedule/backupImpl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package backupschedule

import (
"context"
cloudresourcesv1beta1 "github.com/kyma-project/cloud-manager/api/cloud-resources/v1beta1"
"github.com/kyma-project/cloud-manager/pkg/composed"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sort"
)

type backupImpl interface {
emptySourceObject() composed.ObjWithConditions
emptyBackupList() client.ObjectList
toObjectSlice(list client.ObjectList) []client.Object
getBackupObject(state *State, objectMeta *metav1.ObjectMeta) (client.Object, error)
}

func loadBackupImpl(ctx context.Context, st composed.State) (error, context.Context) {
state := st.(*State)
schedule := state.ObjAsBackupSchedule()
logger := composed.LoggerFromCtx(ctx)

logger.WithValues("BackupSchedule :", schedule.GetName()).Info("Load Provider Specific Implementation")

if _, ok := schedule.(*cloudresourcesv1beta1.GcpNfsBackupSchedule); ok {
state.backupImpl = &backupImplGcpNfs{}
} else {
return composed.UpdateStatus(schedule).
SetExclusiveConditions(metav1.Condition{
Type: cloudresourcesv1beta1.ConditionTypeError,
Status: metav1.ConditionTrue,
Reason: cloudresourcesv1beta1.ReasonUnknownSchedule,
Message: "Error identifying Schedule Provider",
}).
SuccessError(composed.StopWithRequeue).
Run(ctx, state)
}

return nil, nil
}

func getListObjects(list client.ObjectList) []client.Object {
var objects []client.Object

//Retrieve List objects for specific type
if x, ok := list.(*cloudresourcesv1beta1.GcpNfsVolumeList); ok {
for _, item := range x.Items {
objects = append(objects, &item)
}
}

sort.Slice(objects, func(i, j int) bool {
return objects[i].GetCreationTimestamp().Time.Before(objects[j].GetCreationTimestamp().Time)
})
return objects
}
50 changes: 50 additions & 0 deletions pkg/skr/backupschedule/backupImplGcpNfs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package backupschedule

import (
"fmt"
cloudresourcesv1beta1 "github.com/kyma-project/cloud-manager/api/cloud-resources/v1beta1"
"github.com/kyma-project/cloud-manager/pkg/composed"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

type backupImplGcpNfs struct {
}

func (impl *backupImplGcpNfs) emptySourceObject() composed.ObjWithConditions {
return &cloudresourcesv1beta1.GcpNfsVolume{}
}

func (impl *backupImplGcpNfs) emptyBackupList() client.ObjectList {
return &cloudresourcesv1beta1.GcpNfsVolumeBackupList{}
}
func (impl *backupImplGcpNfs) toObjectSlice(list client.ObjectList) []client.Object {
var objects []client.Object

if x, ok := list.(*cloudresourcesv1beta1.GcpNfsVolumeList); ok {
for _, item := range x.Items {
objects = append(objects, &item)
}
}
return objects
}
func (impl *backupImplGcpNfs) getBackupObject(state *State, objectMeta *metav1.ObjectMeta) (client.Object, error) {
schedule := state.ObjAsBackupSchedule()
x, ok := schedule.(*cloudresourcesv1beta1.GcpNfsBackupSchedule)
if !ok {
return nil, fmt.Errorf("provider %s not supported", state.Scope.Spec.Provider)
}

return &cloudresourcesv1beta1.GcpNfsVolumeBackup{
ObjectMeta: *objectMeta,
Spec: cloudresourcesv1beta1.GcpNfsVolumeBackupSpec{
Location: x.Spec.Location,
Source: cloudresourcesv1beta1.GcpNfsVolumeBackupSource{
Volume: cloudresourcesv1beta1.GcpNfsVolumeRef{
Name: schedule.GetSourceRef().Name,
Namespace: schedule.GetSourceRef().Namespace,
},
},
},
}, nil
}
4 changes: 2 additions & 2 deletions pkg/skr/backupschedule/backupschedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ import (
"github.com/kyma-project/cloud-manager/pkg/composed"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

type BackupSchedule interface {
composed.ObjWithConditionsAndState
BackupScheduleSpec
BackupScheduleStatus
GetList() client.ObjectList
}

type BackupScheduleSpec interface {
Expand Down Expand Up @@ -50,4 +48,6 @@ type BackupScheduleStatus interface {
SetActiveSchedule(schedule string)
GetBackupIndex() int
SetBackupIndex(index int)
GetBackupCount() int
SetBackupCount(count int)
}
4 changes: 2 additions & 2 deletions pkg/skr/backupschedule/calculateOnetimeSchedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ func calculateOnetimeSchedule(ctx context.Context, st composed.State) (error, co
return nil, nil
}

//If not one-time backupschedule, continue
//If not one-time schedule, continue
if schedule.GetSchedule() != "" {
return nil, nil
}

logger.WithValues("GcpNfsBackupSchedule :", schedule.GetName()).Info("Evaluating one-time backupschedule")
logger.WithValues("GcpNfsBackupSchedule :", schedule.GetName()).Info("Evaluating one-time schedule")

//If the nextRunTime is already set, continue
if len(schedule.GetNextRunTimes()) > 0 {
Expand Down
2 changes: 1 addition & 1 deletion pkg/skr/backupschedule/calculateOnetimeSchedule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (suite *calculateOnetimeScheduleSuite) TestAlreadySetSchedule() {
state, err := factory.newStateWith(obj)
suite.Nil(err)

//Set the backupschedule
//Set the schedule
obj.Status.NextRunTimes = []string{time.Now().Format(time.RFC3339)}
err = factory.skrCluster.K8sClient().Status().Update(ctx, obj)
suite.Nil(err)
Expand Down
18 changes: 4 additions & 14 deletions pkg/skr/backupschedule/calculateRecurringSchedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func calculateRecurringSchedule(ctx context.Context, st composed.State) (error,
return nil, nil
}

//If one-time backupschedule, continue
//If one-time schedule, continue
if schedule.GetSchedule() == "" {
return nil, nil
}
Expand All @@ -40,24 +40,14 @@ func calculateRecurringSchedule(ctx context.Context, st composed.State) (error,
var nextRunTimes []time.Time
if schedule.GetStartTime() != nil && !schedule.GetStartTime().IsZero() && schedule.GetStartTime().Time.After(now) {
logger.WithValues("GcpNfsBackupSchedule :", schedule.GetName()).Info("StateTime is in future.")
nextRunTimes = state.cronExpression.NextN(schedule.GetStartTime().Time, MaxSchedules)
nextRunTimes = state.cronExpression.NextN(schedule.GetStartTime().Time.UTC(), MaxSchedules)
} else {
logger.WithValues("GcpNfsBackupSchedule :", schedule.GetName()).Info(fmt.Sprintf("Using current time %s", now))
nextRunTimes = state.cronExpression.NextN(now, MaxSchedules)
nextRunTimes = state.cronExpression.NextN(now.UTC(), MaxSchedules)
}
logger.WithValues("GcpNfsBackupSchedule :", schedule.GetName()).Info(fmt.Sprintf("Next RunTime is %v", nextRunTimes[0]))

//If the next run time is after the end time, stop reconciliation
if schedule.GetEndTime() != nil && !schedule.GetEndTime().IsZero() && nextRunTimes[0].After(schedule.GetEndTime().Time) {
logger.WithValues("GcpNfsBackupSchedule :", schedule.GetName()).Info("Next RunTime is after the EndTime. Stopping reconciliation.")
schedule.SetState(cloudresourcesv1beta1.JobStateDone)
schedule.SetNextRunTimes(nil)
return composed.UpdateStatus(schedule).
SuccessError(composed.StopAndForget).
Run(ctx, state)
}

//Update the status of the backupschedule with the next run times
//Update the status of the schedule with the next run times
logger.WithValues("GcpNfsBackupSchedule :", schedule.GetName()).Info("Next RunTime is set. Updating status.")
schedule.SetState(cloudresourcesv1beta1.JobStateActive)
schedule.SetActiveSchedule(schedule.GetSchedule())
Expand Down
Loading

0 comments on commit ae6a8df

Please sign in to comment.