From 8aacea230b3e70f46c14ab36cf76a31b4a4220f7 Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Tue, 6 Jun 2023 17:30:05 +0530 Subject: [PATCH 01/14] Add phase level progress fields in actionset object Signed-off-by: Prasad Ghangal --- pkg/apis/cr/v1alpha1/types.go | 22 ++++++++++++++++++++++ pkg/customresource/actionset.yaml | 28 ++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/pkg/apis/cr/v1alpha1/types.go b/pkg/apis/cr/v1alpha1/types.go index eec65c73ce..716c86c1dc 100644 --- a/pkg/apis/cr/v1alpha1/types.go +++ b/pkg/apis/cr/v1alpha1/types.go @@ -148,6 +148,7 @@ type ActionStatus struct { } // ActionProgress provides information on the progress of an action. +// Combined progress of all the phases. type ActionProgress struct { // RunningPhase represents which phase of the action is being run RunningPhase string `json:"runningPhase,omitempty"` @@ -187,6 +188,27 @@ type Phase struct { State State `json:"state"` // Output is the map of output artifacts produced by the Blueprint phase. Output map[string]interface{} `json:"output,omitempty"` + // Progress represents the phase execution progress. + Progress PhaseProgress `json:"progress,omitempty"` +} + +// PhaseProgress represents the execution state of the phase. +type PhaseProgress struct { + // ProgressPercent represents the execution progress in percentage. + ProgressPercent string `json:"progressPercent,omitempty"` + // SizeUploadedB represents the size of data uploaded in Bytes till now as a part of phase execution. + // This field will be empty for phases which do not involve data movement. + SizeUploadedB int64 `json:"sizeUploadedB,omitempty"` + // EstimatedUploadSizeB represents the total estimated size of data in Bytes + // that will be uploaded during the phase execution. + EstimatedUploadSizeB int64 `json:"estinatedUploadSizeB,omitempty"` + // EstimatedTimeSeconds is the estimated time required in second to upload the + // remaining data estimated with EstimatedUploadSizeB. + // This field will be empty for phases which do not involve data movement. + EstimatedTimeSeconds int64 `json:"estinatedTimeSeconds,omitempty"` + // LastTransitionTime represents the last date time when the progress status + // was received. + LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty"` } // k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/customresource/actionset.yaml b/pkg/customresource/actionset.yaml index db0ee28548..ca00e29bd3 100644 --- a/pkg/customresource/actionset.yaml +++ b/pkg/customresource/actionset.yaml @@ -267,6 +267,20 @@ spec: type: object state: type: string + progress: + properties: + progressPercent: + type: string + sizeUploadedB: + type: integer + estimatedTimeSeconds: + type: integer + estimatedUploadSizeB: + type: integer + lastTransitionTime: + type: string + format: date-time + type: object type: object phases: description: Phases are sub-actions an are executed sequentially. @@ -279,6 +293,20 @@ spec: type: object state: type: string + progress: + properties: + progressPercent: + type: string + sizeUploadedB: + type: integer + estimatedTimeSeconds: + type: integer + estimatedUploadSizeB: + type: integer + lastTransitionTime: + type: string + format: date-time + type: object type: object type: array type: object From 508247ccc5ab505c0285f67133fc7a6a1b3f9cec Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Tue, 6 Jun 2023 17:32:03 +0530 Subject: [PATCH 02/14] Change weight based progress calc with func implementation Signed-off-by: Prasad Ghangal --- pkg/controller/controller.go | 33 +++-- pkg/kanister.go | 2 + pkg/phase.go | 4 + pkg/progress/action.go | 233 ++++++++++++++++------------------- 4 files changed, 140 insertions(+), 132 deletions(-) diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 8221e3d52e..8ad7d9bf68 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -380,14 +380,6 @@ func (c *Controller) handleActionSet(ctx context.Context, t *tomb.Tomb, as *crv1 } } - go func() { - // progress update is computed on a best-effort basis. - // if it exits with error, we will just log it. - if err := progress.TrackActionsProgress(ctx, c.crClient, as.GetName(), as.GetNamespace()); err != nil { - log.Error().WithError(err) - } - }() - for i, a := range as.Status.Actions { var bp *crv1alpha1.Blueprint if bp, err = c.crClient.CrV1alpha1().Blueprints(as.GetNamespace()).Get(ctx, a.Blueprint, v1.GetOptions{}); err != nil { @@ -471,10 +463,21 @@ func (c *Controller) runAction(ctx context.Context, t *tomb.Tomb, as *crv1alpha1 var msg string if err == nil { c.updateActionSetRunningPhase(ctx, as, p.Name()) + progressTrackCtx, doneProgressTrack := context.WithCancel(ctx) + defer doneProgressTrack() + go func() { + // progress update is computed on a best-effort basis. + // if it exits with error, we will just log it. + if err := progress.UpdateActionSetsProgress(progressTrackCtx, c.crClient, as.GetName(), as.GetNamespace(), p); err != nil { + log.Error().WithError(err) + } + }() output, err = p.Exec(ctx, *bp, action.Name, *tp) + doneProgressTrack() } else { msg = fmt.Sprintf("Failed to init phase params: %#v:", as.Status.Actions[aIDX].Phases[i]) } + var rf func(*crv1alpha1.ActionSet) error if err != nil { coreErr = err @@ -491,8 +494,17 @@ func (c *Controller) runAction(ctx context.Context, t *tomb.Tomb, as *crv1alpha1 coreErr = nil rf = func(ras *crv1alpha1.ActionSet) error { ras.Status.Actions[aIDX].Phases[i].State = crv1alpha1.StateComplete + pp, err := p.Progress() + if err != nil { + log.Error().WithError(err) + return nil + } + ras.Status.Actions[aIDX].Phases[i].Progress = pp // this updates the phase output in the actionset status ras.Status.Actions[aIDX].Phases[i].Output = output + if err := progress.SetActionSetPercentCompleted(ras); err != nil { + log.Error().WithError(err) + } return nil } } @@ -528,6 +540,11 @@ func (c *Controller) runAction(ctx context.Context, t *tomb.Tomb, as *crv1alpha1 func (c *Controller) updateActionSetRunningPhase(ctx context.Context, as *crv1alpha1.ActionSet, phase string) { err := reconcile.ActionSet(ctx, c.crClient.CrV1alpha1(), as.Namespace, as.Name, func(as *crv1alpha1.ActionSet) error { as.Status.Progress.RunningPhase = phase + for i := 0; i < len(as.Status.Actions[0].Phases); i++ { + if as.Status.Actions[0].Phases[i].Name == phase { + as.Status.Actions[0].Phases[i].State = crv1alpha1.StateRunning + } + } return nil }) if err != nil { diff --git a/pkg/kanister.go b/pkg/kanister.go index 793814528c..4d2ffb2f8a 100644 --- a/pkg/kanister.go +++ b/pkg/kanister.go @@ -21,6 +21,7 @@ import ( "github.com/Masterminds/semver" "github.com/pkg/errors" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/param" ) @@ -39,6 +40,7 @@ type Func interface { RequiredArgs() []string Arguments() []string Exec(context.Context, param.TemplateParams, map[string]interface{}) (map[string]interface{}, error) + ExecutionProgress() (crv1alpha1.PhaseProgress, error) } // Register allows Funcs to be referenced by User Defined YAMLs diff --git a/pkg/phase.go b/pkg/phase.go index 3d9d45bd33..fb4ee03a8c 100644 --- a/pkg/phase.go +++ b/pkg/phase.go @@ -46,6 +46,10 @@ func (p *Phase) Name() string { return p.name } +func (p *Phase) Progress() (crv1alpha1.PhaseProgress, error) { + return p.f.ExecutionProgress() +} + // Objects returns the phase object references func (p *Phase) Objects() map[string]crv1alpha1.ObjectReference { return p.objects diff --git a/pkg/progress/action.go b/pkg/progress/action.go index db54209816..9a338f0912 100644 --- a/pkg/progress/action.go +++ b/pkg/progress/action.go @@ -2,41 +2,29 @@ package progress import ( "context" - "fmt" "strconv" "time" + "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + kanister "github.com/kanisterio/kanister/pkg" crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/client/clientset/versioned" "github.com/kanisterio/kanister/pkg/field" - fn "github.com/kanisterio/kanister/pkg/function" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/reconcile" "github.com/kanisterio/kanister/pkg/validate" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const ( - progressPercentCompleted = "100.00" - progressPercentStarted = "10.00" - progressPercentNotStarted = "0.00" - weightNormal = 1.0 - weightHeavy = 2.0 - pollDuration = time.Second * 2 -) + pollDuration = time.Second * 5 -var longRunningFuncs = []string{ - fn.BackupDataFuncName, - fn.BackupDataAllFuncName, - fn.RestoreDataFuncName, - fn.RestoreDataAllFuncName, - fn.CopyVolumeDataFuncName, - fn.CreateRDSSnapshotFuncName, - fn.ExportRDSSnapshotToLocFuncName, - fn.RestoreRDSSnapshotFuncName, -} + StartedPercent = "0" + CompletedPercent = "100" +) -// TrackActionsProgress tries to assess the progress of an actionSet by +// UpdateActionSetsProgress tries to assess the progress of an actionSet by // watching the states of all the phases in its actions. It starts an infinite // loop, using a ticker to determine when to assess the phases. The function // returns when the provided context is either done or cancelled. @@ -44,172 +32,169 @@ var longRunningFuncs = []string{ // introducing any latencies on Kanister critical path. // If an error happens while attempting to update the actionSet, the failed // iteration will be skipped with no further retries, until the next tick. -func TrackActionsProgress( +func UpdateActionSetsProgress( ctx context.Context, client versioned.Interface, actionSetName string, namespace string, + p *kanister.Phase, ) error { ticker := time.NewTicker(pollDuration) defer ticker.Stop() - phaseWeights, totalWeight, err := calculatePhaseWeights(ctx, actionSetName, namespace, client) - if err != nil { - return err - } - for { select { case <-ctx.Done(): return ctx.Err() case <-ticker.C: - actionSet, err := client.CrV1alpha1().ActionSets(namespace).Get(ctx, actionSetName, metav1.GetOptions{}) + retry, err := updateActionProgress(ctx, client, actionSetName, namespace, p) if err != nil { - return err - } - - if actionSet.Status == nil { - continue - } - - if err := updateActionsProgress(ctx, client, actionSet, phaseWeights, totalWeight, time.Now()); err != nil { fields := field.M{ - "actionSet": actionSet.Name, + "actionSet": actionSetName, "nextUpdateTime": time.Now().Add(pollDuration), } - log.Error().WithError(err).Print("failed to update phase progress", fields) - continue + log.Error().WithError(err).Print("failed to update action progress", fields) + return err } - - if completedOrFailed(actionSet) { + if !retry { return nil } } } } -func calculatePhaseWeights( +func updateActionProgress( ctx context.Context, + client versioned.Interface, actionSetName string, namespace string, - client versioned.Interface, -) (map[string]float64, float64, error) { - var ( - phaseWeights = map[string]float64{} - totalWeight = 0.0 - ) + p *kanister.Phase, +) (bool, error) { actionSet, err := client.CrV1alpha1().ActionSets(namespace).Get(ctx, actionSetName, metav1.GetOptions{}) if err != nil { - return nil, 0.0, err + return false, errors.Wrap(err, "Failed to get actionset") } - for _, action := range actionSet.Spec.Actions { - blueprintName := action.Blueprint - blueprint, err := client.CrV1alpha1().Blueprints(actionSet.GetNamespace()).Get(ctx, blueprintName, metav1.GetOptions{}) - if err != nil { - return nil, 0.0, err - } - - if err := validate.Blueprint(blueprint); err != nil { - return nil, 0.0, err - } - - blueprintAction, exists := blueprint.Actions[action.Name] - if !exists { - return nil, 0.0, fmt.Errorf("missing blueprint action: %s", action.Name) - } + if actionSet.Status == nil { + return true, nil + } - for _, phase := range blueprintAction.Phases { - phaseWeight := weight(&phase) - phaseWeights[phase.Name] = phaseWeight - totalWeight += phaseWeight - } + if completedOrFailed(actionSet, p.Name()) { + return false, nil } - return phaseWeights, totalWeight, nil + if err := updateActionPhaseProgress(ctx, client, actionSet, p); err != nil { + return true, err + } + return true, nil } -func updateActionsProgress( +func updateActionPhaseProgress( ctx context.Context, client versioned.Interface, actionSet *crv1alpha1.ActionSet, - phaseWeights map[string]float64, - totalWeight float64, - now time.Time, + p *kanister.Phase, ) error { if err := validate.ActionSet(actionSet); err != nil { return err } - // assess the state of the phases in all the actions to determine progress - currentWeight := 0.0 - for _, action := range actionSet.Status.Actions { - for _, phase := range action.Phases { - if phase.State != crv1alpha1.StateComplete { - continue - } - currentWeight += phaseWeights[phase.Name] - } - } - - percent := (currentWeight / totalWeight) * 100.0 - progressPercent := strconv.FormatFloat(percent, 'f', 2, 64) - if progressPercent == progressPercentNotStarted { - progressPercent = progressPercentStarted + phaseProgress, err := p.Progress() + if err != nil { + log.Error().WithError(err).Print("Failed to get progress") + return err } + return updateActionSetStatus(ctx, client, actionSet, p.Name(), phaseProgress) +} +func updateActionSetStatus( + ctx context.Context, + client versioned.Interface, + actionSet *crv1alpha1.ActionSet, + phaseName string, + phaseProgress crv1alpha1.PhaseProgress, +) error { fields := field.M{ "actionSet": actionSet.GetName(), "namespace": actionSet.GetNamespace(), - "progress": progressPercent, + "phase": phaseName, + "progress": phaseProgress.ProgressPercent, } - log.Debug().Print("updating action progress", fields) - - return updateActionSet(ctx, client, actionSet, progressPercent, now) -} - -func weight(phase *crv1alpha1.BlueprintPhase) float64 { - if longRunning(phase) { - return weightHeavy + log.Debug().Print("Updating phase progress", fields) + updateFunc := func(actionSet *crv1alpha1.ActionSet) error { + return setActionSetPhaseProgress(actionSet, phaseName, phaseProgress) } - return weightNormal + if err := reconcile.ActionSet(ctx, client.CrV1alpha1(), actionSet.GetNamespace(), actionSet.GetName(), updateFunc); err != nil { + return err + } + return nil } -func longRunning(phase *crv1alpha1.BlueprintPhase) bool { - for _, f := range longRunningFuncs { - if phase.Func == f { - return true +func completedOrFailed(actionSet *crv1alpha1.ActionSet, phaseName string) bool { + for _, actions := range actionSet.Status.Actions { + for _, phase := range actions.Phases { + if phase.Name != phaseName { + continue + } + return phase.State == crv1alpha1.StateFailed || + phase.State == crv1alpha1.StateComplete } } - return false } -func updateActionSet( - ctx context.Context, - client versioned.Interface, - actionSet *crv1alpha1.ActionSet, - progressPercent string, - lastTransitionTime time.Time, -) error { - updateFunc := func(actionSet *crv1alpha1.ActionSet) error { - metav1Time := metav1.NewTime(lastTransitionTime) - - actionSet.Status.Progress.PercentCompleted = progressPercent - actionSet.Status.Progress.LastTransitionTime = &metav1Time - return nil +func setActionSetPhaseProgress(actionSet *crv1alpha1.ActionSet, phaseName string, phaseProgress crv1alpha1.PhaseProgress) error { + // Update or create phase status in ActionSet status + // Update phase progress if there is a change + for i := 0; i < len(actionSet.Status.Actions); i++ { + for j := 0; j < len(actionSet.Status.Actions[i].Phases); j++ { + if actionSet.Status.Actions[i].Phases[j].Name != phaseName { + continue + } + if actionSet.Status.Actions[i].Phases[j].State == crv1alpha1.StatePending || + actionSet.Status.Actions[i].Phases[j].State == crv1alpha1.StateFailed { + continue + } + if actionSet.Status.Actions[i].Phases[j].Progress.ProgressPercent != phaseProgress.ProgressPercent { + actionSet.Status.Actions[i].Phases[j].Progress = phaseProgress + if err := SetActionSetPercentCompleted(actionSet); err != nil { + return err + } + } + } } + return nil +} - if err := reconcile.ActionSet(ctx, client.CrV1alpha1(), actionSet.GetNamespace(), actionSet.GetName(), updateFunc); err != nil { - return err +// SetActionSetPercentCompleted calculate and set percent completion of the action. The action completion percentage +// is calculated by taking an average of all the involved phases. +func SetActionSetPercentCompleted(actionSet *crv1alpha1.ActionSet) error { + actionProgress := 0 + totalPhases := 0 + for _, actions := range actionSet.Status.Actions { + for _, phase := range actions.Phases { + if phase.Progress.ProgressPercent == "" { + totalPhases++ + continue + } + pp, err := strconv.Atoi(phase.Progress.ProgressPercent) + if err != nil { + return errors.Wrap(err, "Invalid phase progress percent") + } + actionProgress += pp + totalPhases++ + } } + actionProgress = actionProgress / totalPhases + // Update LastTransitionTime only if there is a change in action PercentCompleted + if strconv.Itoa(actionProgress) == actionSet.Status.Progress.PercentCompleted { + return nil + } + metav1Time := metav1.NewTime(time.Now()) + actionSet.Status.Progress.LastTransitionTime = &metav1Time + actionSet.Status.Progress.PercentCompleted = strconv.Itoa(actionProgress) return nil } - -func completedOrFailed(actionSet *crv1alpha1.ActionSet) bool { - return actionSet.Status.State == crv1alpha1.StateFailed || - actionSet.Status.State == crv1alpha1.StateComplete -} From ea1cdd61914813f5179ef140b6a24e8c2d6d6a5f Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Fri, 16 Jun 2023 12:14:52 +0530 Subject: [PATCH 03/14] Refactor and add unit tests for phase progress Signed-off-by: Prasad Ghangal --- pkg/phase_test.go | 13 +- pkg/progress/action_multi_actions_test.go | 221 ++++++++++-------- pkg/progress/action_multi_phases_test.go | 133 ++++++----- pkg/progress/action_single_phase_test.go | 93 +++++--- pkg/progress/action_weighted_funcs_test.go | 255 --------------------- pkg/testutil/func.go | 11 + 6 files changed, 287 insertions(+), 439 deletions(-) delete mode 100644 pkg/progress/action_weighted_funcs_test.go diff --git a/pkg/phase_test.go b/pkg/phase_test.go index aaef64c02c..8c3ae57d2b 100644 --- a/pkg/phase_test.go +++ b/pkg/phase_test.go @@ -21,6 +21,7 @@ import ( crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) type PhaseSuite struct{} @@ -31,8 +32,9 @@ var ( ) type testFunc struct { - output *string - err error + output *string + err error + progressPercent string } type anotherFunc struct { @@ -48,6 +50,9 @@ func (*testFunc) Name() string { } func (tf *testFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + tf.progressPercent = progress.StartedPercent + defer func() { tf.progressPercent = progress.CompletedPercent }() + *tf.output = args["testKey"].(string) return nil, tf.err } @@ -60,6 +65,10 @@ func (tf *testFunc) Arguments() []string { return nil } +func (tf *testFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + return crv1alpha1.PhaseProgress{ProgressPercent: tf.progressPercent}, nil +} + func (s *PhaseSuite) TestExec(c *C) { for _, tc := range []struct { artifact string diff --git a/pkg/progress/action_multi_actions_test.go b/pkg/progress/action_multi_actions_test.go index 7ebddb71dc..a801085386 100644 --- a/pkg/progress/action_multi_actions_test.go +++ b/pkg/progress/action_multi_actions_test.go @@ -2,7 +2,6 @@ package progress import ( "context" - "time" "github.com/kanisterio/kanister/pkg/client/clientset/versioned/fake" . "gopkg.in/check.v1" @@ -31,12 +30,12 @@ func (s *TestSuiteMultiActions) SetUpTest(c *C) { Name: "action-01", Phases: []crv1alpha1.BlueprintPhase{ { - Name: "echo-hello", + Name: "echo-hello-0-0", Func: "echo-hello-func", }, { - Name: "echo-world", - Func: "echo-world-func", + Name: "echo-hello-0-1", + Func: "echo-hello-func", }, }, }, @@ -44,12 +43,12 @@ func (s *TestSuiteMultiActions) SetUpTest(c *C) { Name: "action-02", Phases: []crv1alpha1.BlueprintPhase{ { - Name: "echo-hello", + Name: "echo-hello-1-0", Func: "echo-hello-func", }, { - Name: "echo-world", - Func: "echo-world-func", + Name: "echo-hello-1-1", + Func: "echo-hello-func", }, }, }, @@ -91,11 +90,11 @@ func (s *TestSuiteMultiActions) SetUpTest(c *C) { Name: "action-01", Phases: []crv1alpha1.Phase{ { - Name: "echo-hello", + Name: "echo-hello-0-0", State: crv1alpha1.StatePending, }, { - Name: "echo-world", + Name: "echo-hello-0-1", State: crv1alpha1.StatePending, }, }, @@ -104,11 +103,11 @@ func (s *TestSuiteMultiActions) SetUpTest(c *C) { Name: "action-02", Phases: []crv1alpha1.Phase{ { - Name: "echo-hello", + Name: "echo-hello-1-0", State: crv1alpha1.StatePending, }, { - Name: "echo-world", + Name: "echo-hello-1-1", State: crv1alpha1.StatePending, }, }, @@ -159,145 +158,185 @@ func (s *TestSuiteMultiActions) createFixtures(blueprint *crv1alpha1.Blueprint, } func (s *TestSuiteMultiActions) TestUpdateActionsProgress(c *C) { - now := time.Now() var testCases = []struct { - indexAction int - indexPhase int - phaseState crv1alpha1.State - expected string + indexAction int + indexPhase int + phaseState crv1alpha1.State + phasePercent string + expectedPhasePercent string + expectedActionPercent string }{ { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StatePending, - expected: progressPercentStarted, + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StatePending, + expectedPhasePercent: "", + expectedActionPercent: "", }, { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateRunning, - expected: progressPercentStarted, + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StateRunning, + phasePercent: "40", + expectedPhasePercent: "40", + expectedActionPercent: "10", // Total 4 phases, calculating average to set action progress }, { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "25.00", + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "25", }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StatePending, - expected: "25.00", + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StatePending, + phasePercent: "0", + expectedPhasePercent: "", + expectedActionPercent: "25", }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateRunning, - expected: "25.00", + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StateRunning, + phasePercent: "60", + expectedPhasePercent: "60", + expectedActionPercent: "40", }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateComplete, - expected: "50.00", + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "50", }, { - indexAction: 1, - indexPhase: 0, - phaseState: crv1alpha1.StatePending, - expected: "50.00", + indexAction: 1, + indexPhase: 0, + phaseState: crv1alpha1.StatePending, + expectedPhasePercent: "", + expectedActionPercent: "50", }, { - indexAction: 1, - indexPhase: 0, - phaseState: crv1alpha1.StateRunning, - expected: "50.00", + indexAction: 1, + indexPhase: 0, + phaseState: crv1alpha1.StateRunning, + phasePercent: "37", + expectedPhasePercent: "37", + expectedActionPercent: "59", }, { - indexAction: 1, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "75.00", + indexAction: 1, + indexPhase: 0, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "75", }, { - indexAction: 1, - indexPhase: 1, - phaseState: crv1alpha1.StatePending, - expected: "75.00", + indexAction: 1, + indexPhase: 1, + phaseState: crv1alpha1.StatePending, + phasePercent: "0", + expectedPhasePercent: "", + expectedActionPercent: "75", }, { - indexAction: 1, - indexPhase: 1, - phaseState: crv1alpha1.StateRunning, - expected: "75.00", + indexAction: 1, + indexPhase: 1, + phaseState: crv1alpha1.StateRunning, + phasePercent: "23", + expectedPhasePercent: "23", + expectedActionPercent: "80", }, { - indexAction: 1, - indexPhase: 1, - phaseState: crv1alpha1.StateComplete, - expected: progressPercentCompleted, + indexAction: 1, + indexPhase: 1, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: CompletedPercent, }, } for id, tc := range testCases { + // Get latest rev of actionset resource + as, err := s.clientset.CrV1alpha1().ActionSets(s.actionSet.GetNamespace()).Get(context.Background(), s.actionSet.GetName(), metav1.GetOptions{}) + c.Assert(err, IsNil) assertActionProgress( c, s.clientset, - s.actionSet, - now, + as, tc.indexAction, tc.indexPhase, tc.phaseState, - tc.expected, + tc.phasePercent, + tc.expectedPhasePercent, + tc.expectedActionPercent, id) } } func (s *TestSuiteMultiActions) TestUpdateActionsProgressWithFailures(c *C) { - now := time.Now() var testCases = []struct { - indexAction int - indexPhase int - phaseState crv1alpha1.State - expected string + indexAction int + indexPhase int + phaseState crv1alpha1.State + phasePercent string + expectedPhasePercent string + expectedActionPercent string }{ { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "25.00", + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "25", }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateComplete, - expected: "50.00", + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "50", }, { - indexAction: 1, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "75.00", + indexAction: 1, + indexPhase: 0, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "75", }, { - indexAction: 1, - indexPhase: 1, - phaseState: crv1alpha1.StateFailed, - expected: "75.00", + indexAction: 1, + indexPhase: 1, + phaseState: crv1alpha1.StateFailed, + phasePercent: "30", + expectedPhasePercent: "", + expectedActionPercent: "75", }, } for id, tc := range testCases { + // Get latest rev of actionset resource + as, err := s.clientset.CrV1alpha1().ActionSets(s.actionSet.GetNamespace()).Get(context.Background(), s.actionSet.GetName(), metav1.GetOptions{}) + c.Assert(err, IsNil) assertActionProgress( c, s.clientset, - s.actionSet, - now, + as, tc.indexAction, tc.indexPhase, tc.phaseState, - tc.expected, + tc.phasePercent, + tc.expectedPhasePercent, + tc.expectedActionPercent, id) } } diff --git a/pkg/progress/action_multi_phases_test.go b/pkg/progress/action_multi_phases_test.go index 7d20819171..bfcdac2e49 100644 --- a/pkg/progress/action_multi_phases_test.go +++ b/pkg/progress/action_multi_phases_test.go @@ -2,7 +2,6 @@ package progress import ( "context" - "time" "github.com/kanisterio/kanister/pkg/client/clientset/versioned/fake" . "gopkg.in/check.v1" @@ -31,11 +30,11 @@ func (s *TestSuiteMultiPhases) SetUpTest(c *C) { Name: "action-01", Phases: []crv1alpha1.BlueprintPhase{ { - Name: "echo-hello", + Name: "echo-hello-0-0", Func: "echo-hello-func", }, { - Name: "echo-world", + Name: "echo-hello-0-1", Func: "echo-world-func", }, }, @@ -69,11 +68,11 @@ func (s *TestSuiteMultiPhases) SetUpTest(c *C) { Name: "action-01", Phases: []crv1alpha1.Phase{ { - Name: "echo-hello", + Name: "echo-hello-0-0", State: crv1alpha1.StatePending, }, { - Name: "echo-world", + Name: "echo-hello-0-1", State: crv1alpha1.StatePending, }, }, @@ -123,98 +122,126 @@ func (s *TestSuiteMultiPhases) createFixtures(blueprint *crv1alpha1.Blueprint, a return nil } +//// Test phase percent as per the state of phase but with multiple phases with multiple actions + func (s *TestSuiteMultiPhases) TestUpdateActionsProgress(c *C) { - now := time.Now() var testCases = []struct { - indexAction int - indexPhase int - phaseState crv1alpha1.State - expected string + indexAction int + indexPhase int + phaseState crv1alpha1.State + phasePercent string + expectedPhasePercent string + expectedActionPercent string }{ { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StatePending, - expected: progressPercentStarted, + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StatePending, + phasePercent: "0", + expectedPhasePercent: "", + expectedActionPercent: "", }, { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateRunning, - expected: progressPercentStarted, + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StateRunning, + phasePercent: "30", + expectedPhasePercent: "30", + expectedActionPercent: "15", }, { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "50.00", + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "50", }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StatePending, - expected: "50.00", // stays at 50% because 1st action is done + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StatePending, + phasePercent: "0", + expectedPhasePercent: "", + expectedActionPercent: "50", // stays at 50% because 1st action is done }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateRunning, - expected: "50.00", // stays at 50% because 1st action is done + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StateRunning, + phasePercent: "60", + expectedPhasePercent: "60", + expectedActionPercent: "80", // Averaging out action progress 100(phase-1)+60(phase-2)/2(total phases) }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateComplete, - expected: progressPercentCompleted, + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: CompletedPercent, }, } for id, tc := range testCases { + // Get latest rev of actionset resource + as, err := s.clientset.CrV1alpha1().ActionSets(s.actionSet.GetNamespace()).Get(context.Background(), s.actionSet.GetName(), metav1.GetOptions{}) + c.Assert(err, IsNil) assertActionProgress( c, s.clientset, - s.actionSet, - now, + as, tc.indexAction, tc.indexPhase, tc.phaseState, - tc.expected, + tc.phasePercent, + tc.expectedPhasePercent, + tc.expectedActionPercent, id) } } func (s *TestSuiteMultiPhases) TestUpdateActionsProgressWithFailures(c *C) { - now := time.Now() var testCases = []struct { - indexAction int - indexPhase int - phaseState crv1alpha1.State - expected string + indexAction int + indexPhase int + phaseState crv1alpha1.State + phasePercent string + expectedPhasePercent string + expectedActionPercent string }{ { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "50.00", + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "50", }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateFailed, - expected: "50.00", // stays at 50% because 1st action is done + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StateFailed, + phasePercent: "30", + expectedPhasePercent: "", + expectedActionPercent: "50", // stays at 50% because 1st action is done }, } for id, tc := range testCases { + // Get latest rev of actionset resource + as, err := s.clientset.CrV1alpha1().ActionSets(s.actionSet.GetNamespace()).Get(context.Background(), s.actionSet.GetName(), metav1.GetOptions{}) + c.Assert(err, IsNil) assertActionProgress( c, s.clientset, - s.actionSet, - now, + as, tc.indexAction, tc.indexPhase, tc.phaseState, - tc.expected, + tc.phasePercent, + tc.expectedPhasePercent, + tc.expectedActionPercent, id) } } diff --git a/pkg/progress/action_single_phase_test.go b/pkg/progress/action_single_phase_test.go index c512683c25..cfbc9b3d97 100644 --- a/pkg/progress/action_single_phase_test.go +++ b/pkg/progress/action_single_phase_test.go @@ -2,9 +2,10 @@ package progress import ( "context" + "fmt" "testing" - "time" + kanister "github.com/kanisterio/kanister/pkg" "github.com/kanisterio/kanister/pkg/client/clientset/versioned" "github.com/kanisterio/kanister/pkg/client/clientset/versioned/fake" . "gopkg.in/check.v1" @@ -27,6 +28,7 @@ type TestSuiteSinglePhase struct { blueprint *crv1alpha1.Blueprint actionSet *crv1alpha1.ActionSet clientset *fake.Clientset + mockPhase *kanister.Phase } var _ = Suite(&TestSuiteSinglePhase{}) @@ -43,7 +45,7 @@ func (s *TestSuiteSinglePhase) SetUpTest(c *C) { Name: "action-01", Phases: []crv1alpha1.BlueprintPhase{ { - Name: "echo-hello", + Name: "echo-hello-0-0", Func: "echo-hello-func", }, }, @@ -77,7 +79,7 @@ func (s *TestSuiteSinglePhase) SetUpTest(c *C) { Name: "action-01", Phases: []crv1alpha1.Phase{ { - Name: "echo-hello", + Name: "echo-hello-0-0", State: crv1alpha1.StatePending, }, }, @@ -127,42 +129,56 @@ func (s *TestSuiteSinglePhase) createFixtures(blueprint *crv1alpha1.Blueprint, a return nil } -func (s *TestSuiteSinglePhase) TestUpdateActionsProgress(c *C) { - now := time.Now() +func (s *TestSuiteSinglePhase) TestUpdateActionPhaseProgress(c *C) { var testCases = []struct { - indexAction int - indexPhase int - phaseState crv1alpha1.State - expected string + indexAction int + indexPhase int + phaseState crv1alpha1.State + phasePercent string + expectedPhasePercent string + expectedActionPercent string }{ { - phaseState: crv1alpha1.StatePending, - expected: progressPercentStarted, + phaseState: crv1alpha1.StatePending, + expectedPhasePercent: "", + expectedActionPercent: "", }, { - phaseState: crv1alpha1.StateRunning, - expected: progressPercentStarted, + phaseState: crv1alpha1.StateRunning, + phasePercent: "20", + expectedPhasePercent: "20", + expectedActionPercent: "20", }, { - phaseState: crv1alpha1.StateFailed, - expected: progressPercentStarted, + phaseState: crv1alpha1.StateRunning, + phasePercent: "50", + expectedPhasePercent: "50", + expectedActionPercent: "50", }, { - phaseState: crv1alpha1.StateComplete, - expected: progressPercentCompleted, + phaseState: crv1alpha1.StateFailed, + phasePercent: "50", + expectedPhasePercent: "", + expectedActionPercent: "", + }, + { + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: CompletedPercent, }, } - for id, tc := range testCases { assertActionProgress( c, s.clientset, s.actionSet, - now, tc.indexAction, tc.indexPhase, tc.phaseState, - tc.expected, + tc.phasePercent, + tc.expectedPhasePercent, + tc.expectedActionPercent, id) } } @@ -171,28 +187,29 @@ func assertActionProgress( c *C, clientset versioned.Interface, actionSet *crv1alpha1.ActionSet, - now time.Time, indexAction int, indexPhase int, - newState crv1alpha1.State, - expectedPercentCompleted string, + phaseState crv1alpha1.State, + phasePercent string, + expectedPhasePercent string, + expectedActionPercent string, testCaseID int) { - // update the phase state - actionSet.Status.Actions[indexAction].Phases[indexPhase].State = newState + now := metav1.Now() + actionSet.Status.Actions[indexAction].Phases[indexPhase].State = phaseState updated, err := clientset.CrV1alpha1().ActionSets(actionSet.GetNamespace()).Update(context.Background(), actionSet, metav1.UpdateOptions{}) c.Assert(err, IsNil) - - // calculate and update the progress so that it reflects the state change - phaseWeights, totalWeight, err := calculatePhaseWeights(context.Background(), actionSet.GetName(), actionSet.GetNamespace(), clientset) - c.Assert(err, IsNil) - - updateErr := updateActionsProgress(context.Background(), clientset, updated, phaseWeights, totalWeight, now) - c.Assert(updateErr, IsNil) - - // retrieve the latest actionSet resource to confirm its progress data + phaseName := fmt.Sprintf("echo-hello-%d-%d", indexAction, indexPhase) + err1 := updateActionSetStatus(context.Background(), clientset, actionSet, phaseName, crv1alpha1.PhaseProgress{ProgressPercent: phasePercent, LastTransitionTime: &now}) + c.Assert(err1, IsNil, Commentf("test case #: %d", testCaseID)) actual, err := clientset.CrV1alpha1().ActionSets(actionSet.GetNamespace()).Get(context.Background(), updated.GetName(), metav1.GetOptions{}) - c.Assert(err, IsNil, Commentf("test case #: %d", testCaseID)) - c.Assert(actual.Status.Progress.PercentCompleted, Equals, expectedPercentCompleted, Commentf("test case #: %d", testCaseID)) - c.Assert(actual.Status.Progress.LastTransitionTime, NotNil) - c.Assert(actual.Status.Progress.LastTransitionTime.Time, Equals, now, Commentf("test case #: %d", testCaseID)) + c.Assert(err, IsNil) + // Check phase progress percent + c.Assert(actual.Status.Actions[indexAction].Phases[indexPhase].Progress.ProgressPercent, Equals, expectedPhasePercent, Commentf("test case #: %d", testCaseID)) + // Check action progress percent + c.Assert(actual.Status.Progress.PercentCompleted, Equals, expectedActionPercent, Commentf("test case #: %d", testCaseID)) + if phaseState != crv1alpha1.StateFailed && + phaseState != crv1alpha1.StatePending { + c.Assert(actual.Status.Actions[indexAction].Phases[indexPhase].Progress.LastTransitionTime, NotNil) + c.Assert(*actual.Status.Actions[indexAction].Phases[indexPhase].Progress.LastTransitionTime, Equals, now, Commentf("test case #: %d", testCaseID)) + } } diff --git a/pkg/progress/action_weighted_funcs_test.go b/pkg/progress/action_weighted_funcs_test.go deleted file mode 100644 index ea39ca0b3c..0000000000 --- a/pkg/progress/action_weighted_funcs_test.go +++ /dev/null @@ -1,255 +0,0 @@ -package progress - -import ( - "context" - "time" - - "github.com/kanisterio/kanister/pkg/client/clientset/versioned/fake" - . "gopkg.in/check.v1" - - crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -type TestSuiteWeightedFuncs struct { - blueprint *crv1alpha1.Blueprint - actionSet *crv1alpha1.ActionSet - clientset *fake.Clientset -} - -var _ = Suite(&TestSuiteWeightedFuncs{}) - -func (s *TestSuiteWeightedFuncs) SetUpTest(c *C) { - mockBlueprint := &crv1alpha1.Blueprint{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{ - Name: testBlueprint, - Namespace: testNamespace, - }, - Actions: map[string]*crv1alpha1.BlueprintAction{ - "action-weighted": { - Name: "action-weighted", - Phases: []crv1alpha1.BlueprintPhase{ - { - Name: "echo-00", - Func: "BackupData", - }, - { - Name: "echo-01", - Func: "CopyVolumeData", - }, - }, - }, - "action-normal": { - Name: "action-normal", - Phases: []crv1alpha1.BlueprintPhase{ - { - Name: "echo-02", - Func: "echo-hello-func", - }, - { - Name: "echo-03", - Func: "echo-hello-func", - }, - }, - }, - }, - } - - mockActionSet := &crv1alpha1.ActionSet{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{ - Name: testActionset, - Namespace: testNamespace, - }, - Spec: &crv1alpha1.ActionSetSpec{ - Actions: []crv1alpha1.ActionSpec{ - { - Name: "action-weighted", - Object: crv1alpha1.ObjectReference{ - APIVersion: "v1", - Group: "", - Resource: "Namespace", - }, - Blueprint: testBlueprint, - }, - { - Name: "action-normal", - Object: crv1alpha1.ObjectReference{ - APIVersion: "v1", - Group: "", - Resource: "Namespace", - }, - Blueprint: testBlueprint, - }, - }, - }, - Status: &crv1alpha1.ActionSetStatus{ - State: crv1alpha1.StateRunning, - Actions: []crv1alpha1.ActionStatus{ - { - Name: "action-weighted", - Phases: []crv1alpha1.Phase{ - { - Name: "echo-00", - State: crv1alpha1.StatePending, - }, - { - Name: "echo-01", - State: crv1alpha1.StatePending, - }, - }, - }, - { - Name: "action-normal", - Phases: []crv1alpha1.Phase{ - { - Name: "echo-02", - State: crv1alpha1.StatePending, - }, - { - Name: "echo-03", - State: crv1alpha1.StatePending, - }, - }, - }, - }, - }, - } - - s.clientset = fake.NewSimpleClientset() - err := s.createFixtures(mockBlueprint, mockActionSet) - c.Assert(err, IsNil) -} - -func (s *TestSuiteWeightedFuncs) TearDownTest(c *C) { - blueprintErr := s.clientset.CrV1alpha1().Blueprints(s.blueprint.GetNamespace()).Delete( - context.Background(), - s.blueprint.GetName(), - metav1.DeleteOptions{}) - c.Assert(blueprintErr, IsNil) - - actionSetErr := s.clientset.CrV1alpha1().ActionSets(s.actionSet.GetNamespace()).Delete( - context.Background(), - s.actionSet.GetName(), - metav1.DeleteOptions{}) - c.Assert(actionSetErr, IsNil) -} - -func (s *TestSuiteWeightedFuncs) createFixtures(blueprint *crv1alpha1.Blueprint, actionSet *crv1alpha1.ActionSet) error { - createdBlueprint, err := s.clientset.CrV1alpha1().Blueprints(blueprint.GetNamespace()).Create( - context.Background(), - blueprint, - metav1.CreateOptions{}) - if err != nil { - return err - } - s.blueprint = createdBlueprint - - createdActionSet, err := s.clientset.CrV1alpha1().ActionSets(actionSet.GetNamespace()).Create( - context.Background(), - actionSet, - metav1.CreateOptions{}) - if err != nil { - return err - } - s.actionSet = createdActionSet - - return nil -} - -func (s *TestSuiteWeightedFuncs) TestUpdateActionsProgress(c *C) { - now := time.Now() - var testCases = []struct { - indexAction int - indexPhase int - phaseState crv1alpha1.State - expected string - }{ - { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StatePending, - expected: progressPercentStarted, - }, - { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateRunning, - expected: progressPercentStarted, - }, - { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "33.33", - }, - { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StatePending, - expected: "33.33", - }, - { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateRunning, - expected: "33.33", - }, - { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateComplete, - expected: "66.67", - }, - { - indexAction: 1, - indexPhase: 0, - phaseState: crv1alpha1.StatePending, - expected: "66.67", - }, - { - indexAction: 1, - indexPhase: 0, - phaseState: crv1alpha1.StateRunning, - expected: "66.67", - }, - { - indexAction: 1, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "83.33", - }, - { - indexAction: 1, - indexPhase: 1, - phaseState: crv1alpha1.StatePending, - expected: "83.33", - }, - { - indexAction: 1, - indexPhase: 1, - phaseState: crv1alpha1.StateRunning, - expected: "83.33", - }, - { - indexAction: 1, - indexPhase: 1, - phaseState: crv1alpha1.StateComplete, - expected: progressPercentCompleted, - }, - } - - for id, tc := range testCases { - assertActionProgress( - c, - s.clientset, - s.actionSet, - now, - tc.indexAction, - tc.indexPhase, - tc.phaseState, - tc.expected, - id) - } -} diff --git a/pkg/testutil/func.go b/pkg/testutil/func.go index e05ae68a92..e2f45f445b 100644 --- a/pkg/testutil/func.go +++ b/pkg/testutil/func.go @@ -16,11 +16,15 @@ package testutil import ( "context" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( @@ -112,6 +116,13 @@ func (mf *mockKanisterFunc) Exec(ctx context.Context, tp param.TemplateParams, a func (mf *mockKanisterFunc) Name() string { return mf.name } +func (mf *mockKanisterFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: progress.StartedPercent, + LastTransitionTime: &metav1Time, + }, nil +} func FailFuncError() error { return <-failFuncCh From 35c55783db5e167af9f0df4edcbbd24a1fbb9ef2 Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Fri, 16 Jun 2023 12:15:21 +0530 Subject: [PATCH 04/14] Update generated deepcopy methods Signed-off-by: Prasad Ghangal --- pkg/apis/cr/v1alpha1/zz_generated.deepcopy.go | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/pkg/apis/cr/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/cr/v1alpha1/zz_generated.deepcopy.go index d28ff12c9d..97952bc7d9 100644 --- a/pkg/apis/cr/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/cr/v1alpha1/zz_generated.deepcopy.go @@ -618,6 +618,26 @@ func (in *Phase) DeepCopy() *Phase { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PhaseProgress) DeepCopyInto(out *PhaseProgress) { + *out = *in + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = (*in).DeepCopy() + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PhaseProgress. +func (in *PhaseProgress) DeepCopy() *PhaseProgress { + if in == nil { + return nil + } + out := new(PhaseProgress) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Profile) DeepCopyInto(out *Profile) { *out = *in From 72c2bb678c22c9d75c23d74bd1eb94199b4ea1ac Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Mon, 19 Jun 2023 12:38:22 +0530 Subject: [PATCH 05/14] Fix import cycle issue in test Signed-off-by: Prasad Ghangal --- pkg/phase_test.go | 5 ++--- pkg/progress/action_multi_phases_test.go | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pkg/phase_test.go b/pkg/phase_test.go index 8c3ae57d2b..3ae63a09d7 100644 --- a/pkg/phase_test.go +++ b/pkg/phase_test.go @@ -21,7 +21,6 @@ import ( crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/param" - "github.com/kanisterio/kanister/pkg/progress" ) type PhaseSuite struct{} @@ -50,8 +49,8 @@ func (*testFunc) Name() string { } func (tf *testFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { - tf.progressPercent = progress.StartedPercent - defer func() { tf.progressPercent = progress.CompletedPercent }() + tf.progressPercent = "0" + defer func() { tf.progressPercent = "100" }() *tf.output = args["testKey"].(string) return nil, tf.err diff --git a/pkg/progress/action_multi_phases_test.go b/pkg/progress/action_multi_phases_test.go index bfcdac2e49..f33b087d65 100644 --- a/pkg/progress/action_multi_phases_test.go +++ b/pkg/progress/action_multi_phases_test.go @@ -122,8 +122,6 @@ func (s *TestSuiteMultiPhases) createFixtures(blueprint *crv1alpha1.Blueprint, a return nil } -//// Test phase percent as per the state of phase but with multiple phases with multiple actions - func (s *TestSuiteMultiPhases) TestUpdateActionsProgress(c *C) { var testCases = []struct { indexAction int From 68a075ee6c42c49b75b074ffb05bb42466bfc550 Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Fri, 4 Aug 2023 11:59:46 +0530 Subject: [PATCH 06/14] Update pkg/apis/cr/v1alpha1/types.go Co-authored-by: Pavan Navarathna <6504783+pavannd1@users.noreply.github.com> --- pkg/apis/cr/v1alpha1/types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/apis/cr/v1alpha1/types.go b/pkg/apis/cr/v1alpha1/types.go index 716c86c1dc..71c0966b59 100644 --- a/pkg/apis/cr/v1alpha1/types.go +++ b/pkg/apis/cr/v1alpha1/types.go @@ -147,8 +147,8 @@ type ActionStatus struct { DeferPhase Phase `json:"deferPhase,omitempty"` } -// ActionProgress provides information on the progress of an action. -// Combined progress of all the phases. +// ActionProgress provides information on the combined progress +// of all the phases in the action. type ActionProgress struct { // RunningPhase represents which phase of the action is being run RunningPhase string `json:"runningPhase,omitempty"` From b0e53a5a1fde8d571bc4608b6c9ee722bda94d6a Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Fri, 4 Aug 2023 12:00:16 +0530 Subject: [PATCH 07/14] Update pkg/apis/cr/v1alpha1/types.go Co-authored-by: Pavan Navarathna <6504783+pavannd1@users.noreply.github.com> --- pkg/apis/cr/v1alpha1/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/apis/cr/v1alpha1/types.go b/pkg/apis/cr/v1alpha1/types.go index 71c0966b59..ee23dec476 100644 --- a/pkg/apis/cr/v1alpha1/types.go +++ b/pkg/apis/cr/v1alpha1/types.go @@ -196,7 +196,7 @@ type Phase struct { type PhaseProgress struct { // ProgressPercent represents the execution progress in percentage. ProgressPercent string `json:"progressPercent,omitempty"` - // SizeUploadedB represents the size of data uploaded in Bytes till now as a part of phase execution. + // SizeUploadedB represents the size of data uploaded in Bytes at a given time during phase execution. // This field will be empty for phases which do not involve data movement. SizeUploadedB int64 `json:"sizeUploadedB,omitempty"` // EstimatedUploadSizeB represents the total estimated size of data in Bytes From 8da47fa87325c321cc36c62d7fc2c89033aafce2 Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Fri, 4 Aug 2023 12:02:28 +0530 Subject: [PATCH 08/14] Update pkg/apis/cr/v1alpha1/types.go Co-authored-by: Pavan Navarathna <6504783+pavannd1@users.noreply.github.com> --- pkg/apis/cr/v1alpha1/types.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/apis/cr/v1alpha1/types.go b/pkg/apis/cr/v1alpha1/types.go index ee23dec476..85d2745928 100644 --- a/pkg/apis/cr/v1alpha1/types.go +++ b/pkg/apis/cr/v1alpha1/types.go @@ -201,6 +201,7 @@ type PhaseProgress struct { SizeUploadedB int64 `json:"sizeUploadedB,omitempty"` // EstimatedUploadSizeB represents the total estimated size of data in Bytes // that will be uploaded during the phase execution. + // This field will be empty for phases which do not involve data movement. EstimatedUploadSizeB int64 `json:"estinatedUploadSizeB,omitempty"` // EstimatedTimeSeconds is the estimated time required in second to upload the // remaining data estimated with EstimatedUploadSizeB. From 090539bc2157228e14afda7356e45a8e87d29ff7 Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Fri, 4 Aug 2023 12:02:51 +0530 Subject: [PATCH 09/14] Update pkg/apis/cr/v1alpha1/types.go Co-authored-by: Pavan Navarathna <6504783+pavannd1@users.noreply.github.com> --- pkg/apis/cr/v1alpha1/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/apis/cr/v1alpha1/types.go b/pkg/apis/cr/v1alpha1/types.go index 85d2745928..1aa90de0fd 100644 --- a/pkg/apis/cr/v1alpha1/types.go +++ b/pkg/apis/cr/v1alpha1/types.go @@ -203,7 +203,7 @@ type PhaseProgress struct { // that will be uploaded during the phase execution. // This field will be empty for phases which do not involve data movement. EstimatedUploadSizeB int64 `json:"estinatedUploadSizeB,omitempty"` - // EstimatedTimeSeconds is the estimated time required in second to upload the + // EstimatedTimeSeconds is the estimated time required in seconds to upload the // remaining data estimated with EstimatedUploadSizeB. // This field will be empty for phases which do not involve data movement. EstimatedTimeSeconds int64 `json:"estinatedTimeSeconds,omitempty"` From 55292754a9551b26aef13029205d5f495d04aadc Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Fri, 11 Aug 2023 12:05:24 +0530 Subject: [PATCH 10/14] Use correct action index while updating action phase state Signed-off-by: Prasad Ghangal --- pkg/controller/controller.go | 15 ++++++++------- pkg/phase.go | 1 + pkg/progress/action.go | 20 ++++++++++---------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 8ad7d9bf68..262c37ae8e 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -446,7 +446,7 @@ func (c *Controller) runAction(ctx context.Context, t *tomb.Tomb, as *crv1alpha1 defer func() { var deferErr error if deferPhase != nil { - c.updateActionSetRunningPhase(ctx, as, deferPhase.Name()) + c.updateActionSetRunningPhase(ctx, aIDX, as, deferPhase.Name()) deferErr = c.executeDeferPhase(ctx, deferPhase, tp, bp, action.Name, aIDX, as) } // render artifacts only if all the phases are run successfully @@ -462,13 +462,13 @@ func (c *Controller) runAction(ctx context.Context, t *tomb.Tomb, as *crv1alpha1 var output map[string]interface{} var msg string if err == nil { - c.updateActionSetRunningPhase(ctx, as, p.Name()) + c.updateActionSetRunningPhase(ctx, aIDX, as, p.Name()) progressTrackCtx, doneProgressTrack := context.WithCancel(ctx) defer doneProgressTrack() go func() { // progress update is computed on a best-effort basis. // if it exits with error, we will just log it. - if err := progress.UpdateActionSetsProgress(progressTrackCtx, c.crClient, as.GetName(), as.GetNamespace(), p); err != nil { + if err := progress.UpdateActionSetsProgress(progressTrackCtx, aIDX, c.crClient, as.GetName(), as.GetNamespace(), p); err != nil { log.Error().WithError(err) } }() @@ -537,12 +537,13 @@ func (c *Controller) runAction(ctx context.Context, t *tomb.Tomb, as *crv1alpha1 // updateActionSetRunningPhase updates the actionset's `status.Progress.RunningPhase` with the phase name // that is being run currently. It doesn't fail if there was a problem updating the actionset. It just logs // the failure. -func (c *Controller) updateActionSetRunningPhase(ctx context.Context, as *crv1alpha1.ActionSet, phase string) { +func (c *Controller) updateActionSetRunningPhase(ctx context.Context, aIDX int, as *crv1alpha1.ActionSet, phase string) { err := reconcile.ActionSet(ctx, c.crClient.CrV1alpha1(), as.Namespace, as.Name, func(as *crv1alpha1.ActionSet) error { as.Status.Progress.RunningPhase = phase - for i := 0; i < len(as.Status.Actions[0].Phases); i++ { - if as.Status.Actions[0].Phases[i].Name == phase { - as.Status.Actions[0].Phases[i].State = crv1alpha1.StateRunning + // Iterate through all the phases and set current phase state to running + for i := 0; i < len(as.Status.Actions[aIDX].Phases); i++ { + if as.Status.Actions[aIDX].Phases[i].Name == phase { + as.Status.Actions[aIDX].Phases[i].State = crv1alpha1.StateRunning } } return nil diff --git a/pkg/phase.go b/pkg/phase.go index fb4ee03a8c..87198b551c 100644 --- a/pkg/phase.go +++ b/pkg/phase.go @@ -46,6 +46,7 @@ func (p *Phase) Name() string { return p.name } +// Progress return execution progress of the phase. func (p *Phase) Progress() (crv1alpha1.PhaseProgress, error) { return p.f.ExecutionProgress() } diff --git a/pkg/progress/action.go b/pkg/progress/action.go index 9a338f0912..8e80aec06b 100644 --- a/pkg/progress/action.go +++ b/pkg/progress/action.go @@ -34,6 +34,7 @@ const ( // iteration will be skipped with no further retries, until the next tick. func UpdateActionSetsProgress( ctx context.Context, + aIDX int, client versioned.Interface, actionSetName string, namespace string, @@ -48,7 +49,7 @@ func UpdateActionSetsProgress( return ctx.Err() case <-ticker.C: - retry, err := updateActionProgress(ctx, client, actionSetName, namespace, p) + retry, err := updateActionProgress(ctx, aIDX, client, actionSetName, namespace, p) if err != nil { fields := field.M{ "actionSet": actionSetName, @@ -66,6 +67,7 @@ func UpdateActionSetsProgress( func updateActionProgress( ctx context.Context, + aIDX int, client versioned.Interface, actionSetName string, namespace string, @@ -81,7 +83,7 @@ func updateActionProgress( return true, nil } - if completedOrFailed(actionSet, p.Name()) { + if completedOrFailed(aIDX, actionSet, p.Name()) { return false, nil } @@ -132,15 +134,13 @@ func updateActionSetStatus( return nil } -func completedOrFailed(actionSet *crv1alpha1.ActionSet, phaseName string) bool { - for _, actions := range actionSet.Status.Actions { - for _, phase := range actions.Phases { - if phase.Name != phaseName { - continue - } - return phase.State == crv1alpha1.StateFailed || - phase.State == crv1alpha1.StateComplete +func completedOrFailed(aIDX int, actionSet *crv1alpha1.ActionSet, phaseName string) bool { + for _, phase := range actionSet.Status.Actions[aIDX].Phases { + if phase.Name != phaseName { + continue } + return phase.State == crv1alpha1.StateFailed || + phase.State == crv1alpha1.StateComplete } return false } From 5822e8d1f536a086534e73e1f2c8af29bd865d1e Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Tue, 26 Sep 2023 12:23:21 +0530 Subject: [PATCH 11/14] Implement ExecutionProgress method on Kanister functions (#2117) * Implement ExecutionProgress method on Kanister functions Signed-off-by: Prasad Ghangal * Set LastTransitionTime in ExecutionProgress return Signed-off-by: Prasad Ghangal * Update pkg/function/backup_data.go Co-authored-by: Pavan Navarathna <6504783+pavannd1@users.noreply.github.com> --------- Signed-off-by: Prasad Ghangal Co-authored-by: Pavan Navarathna <6504783+pavannd1@users.noreply.github.com> --- pkg/function/backup_data.go | 22 +++++++++++++++++-- pkg/function/backup_data_all.go | 22 +++++++++++++++++-- pkg/function/backup_data_stats.go | 21 ++++++++++++++++-- .../backup_data_using_kopia_server.go | 22 +++++++++++++++++-- pkg/function/checkRepository.go | 20 +++++++++++++++-- pkg/function/copy_volume_data.go | 21 ++++++++++++++++-- pkg/function/create_csi_snapshot.go | 22 +++++++++++++++++-- pkg/function/create_csi_snapshot_static.go | 22 +++++++++++++++++-- pkg/function/create_rds_snapshot.go | 20 ++++++++++++++++- pkg/function/create_volume_from_snapshot.go | 21 ++++++++++++++++-- pkg/function/create_volume_snapshot.go | 20 +++++++++++++++-- pkg/function/delete_csi_snapshot.go | 22 +++++++++++++++++-- pkg/function/delete_csi_snapshot_content.go | 22 +++++++++++++++++-- pkg/function/delete_data.go | 21 ++++++++++++++++-- pkg/function/delete_data_all.go | 22 +++++++++++++++++-- .../delete_data_using_kopia_server.go | 22 +++++++++++++++++-- pkg/function/delete_rds_snapshot.go | 20 ++++++++++++++++- pkg/function/delete_volume_snapshot.go | 22 +++++++++++++++++-- pkg/function/describe_backups.go | 21 ++++++++++++++++-- pkg/function/export_rds_snapshot_location.go | 19 +++++++++++++++- pkg/function/kube_exec.go | 20 ++++++++++++++++- pkg/function/kube_exec_all.go | 22 +++++++++++++++++-- pkg/function/kube_task.go | 19 +++++++++++++++- pkg/function/kubeops.go | 20 +++++++++++++++-- pkg/function/location_delete.go | 22 +++++++++++++++++-- pkg/function/prepare_data.go | 20 +++++++++++++++-- pkg/function/restore_csi_snapshot.go | 21 ++++++++++++++++-- pkg/function/restore_data.go | 20 +++++++++++++++-- pkg/function/restore_data_all.go | 21 ++++++++++++++++-- .../restore_data_using_kopia_server.go | 20 +++++++++++++++-- pkg/function/restore_rds_snapshot.go | 22 +++++++++++++++++-- pkg/function/scale_workload.go | 22 +++++++++++++++++-- pkg/function/wait.go | 19 ++++++++++++++-- pkg/function/wait_for_snapshot_completion.go | 22 +++++++++++++++++-- pkg/function/waitv2.go | 21 ++++++++++++++++-- 35 files changed, 670 insertions(+), 65 deletions(-) diff --git a/pkg/function/backup_data.go b/pkg/function/backup_data.go index f8210eda28..8dc2396cd4 100644 --- a/pkg/function/backup_data.go +++ b/pkg/function/backup_data.go @@ -16,18 +16,22 @@ package function import ( "context" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/consts" "github.com/kanisterio/kanister/pkg/field" "github.com/kanisterio/kanister/pkg/format" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -64,13 +68,19 @@ func init() { var _ kanister.Func = (*backupDataFunc)(nil) -type backupDataFunc struct{} +type backupDataFunc struct { + progressPercent string +} func (*backupDataFunc) Name() string { return BackupDataFuncName } -func (*backupDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (b *backupDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + b.progressPercent = progress.StartedPercent + defer func() { b.progressPercent = progress.CompletedPercent }() + var namespace, pod, container, includePath, backupArtifactPrefix, encryptionKey string var err error if err = Arg(args, BackupDataNamespaceArg, &namespace); err != nil { @@ -188,3 +198,11 @@ func backupData(ctx context.Context, cli kubernetes.Interface, namespace, pod, c phySize: phySize, }, nil } + +func (b *backupDataFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: b.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/backup_data_all.go b/pkg/function/backup_data_all.go index 66cece7ded..00b56c91dd 100644 --- a/pkg/function/backup_data_all.go +++ b/pkg/function/backup_data_all.go @@ -19,15 +19,19 @@ import ( "encoding/json" "fmt" "strings" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/consts" "github.com/kanisterio/kanister/pkg/field" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -62,13 +66,19 @@ func init() { var _ kanister.Func = (*backupDataAllFunc)(nil) -type backupDataAllFunc struct{} +type backupDataAllFunc struct { + progressPercent string +} func (*backupDataAllFunc) Name() string { return BackupDataAllFuncName } -func (*backupDataAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (b *backupDataAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + b.progressPercent = progress.StartedPercent + defer func() { b.progressPercent = progress.CompletedPercent }() + var namespace, pods, container, includePath, backupArtifactPrefix, encryptionKey string var err error if err = Arg(args, BackupDataAllNamespaceArg, &namespace); err != nil { @@ -172,3 +182,11 @@ func backupDataAll(ctx context.Context, cli kubernetes.Interface, namespace stri FunctionOutputVersion: kanister.DefaultVersion, }, nil } + +func (b *backupDataAllFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: b.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/backup_data_stats.go b/pkg/function/backup_data_stats.go index 3f23fe4f84..012581e99e 100644 --- a/pkg/function/backup_data_stats.go +++ b/pkg/function/backup_data_stats.go @@ -17,8 +17,10 @@ package function import ( "bytes" "context" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" @@ -27,6 +29,7 @@ import ( "github.com/kanisterio/kanister/pkg/format" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -56,7 +59,9 @@ func init() { var _ kanister.Func = (*BackupDataStatsFunc)(nil) -type BackupDataStatsFunc struct{} +type BackupDataStatsFunc struct { + progressPercent string +} func (*BackupDataStatsFunc) Name() string { return BackupDataStatsFuncName @@ -130,7 +135,11 @@ func backupDataStatsPodFunc( } } -func (*BackupDataStatsFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (b *BackupDataStatsFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + b.progressPercent = progress.StartedPercent + defer func() { b.progressPercent = progress.CompletedPercent }() + var namespace, backupArtifactPrefix, backupID, mode, encryptionKey string var err error if err = Arg(args, BackupDataStatsNamespaceArg, &namespace); err != nil { @@ -183,3 +192,11 @@ func (*BackupDataStatsFunc) Arguments() []string { BackupDataStatsEncryptionKeyArg, } } + +func (b *BackupDataStatsFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: b.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/backup_data_using_kopia_server.go b/pkg/function/backup_data_using_kopia_server.go index 19e542dc7e..cab01e988a 100644 --- a/pkg/function/backup_data_using_kopia_server.go +++ b/pkg/function/backup_data_using_kopia_server.go @@ -19,18 +19,22 @@ import ( "encoding/base64" "encoding/json" "strings" + "time" "github.com/dustin/go-humanize" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/format" kankopia "github.com/kanisterio/kanister/pkg/kopia" kopiacmd "github.com/kanisterio/kanister/pkg/kopia/command" kerrors "github.com/kanisterio/kanister/pkg/kopia/errors" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/utils" ) @@ -42,7 +46,9 @@ const ( KopiaRepositoryServerUserHostname = "repositoryServerUserHostname" ) -type backupDataUsingKopiaServerFunc struct{} +type backupDataUsingKopiaServerFunc struct { + progressPercent string +} func init() { err := kanister.Register(&backupDataUsingKopiaServerFunc{}) @@ -77,7 +83,11 @@ func (*backupDataUsingKopiaServerFunc) Arguments() []string { } } -func (*backupDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]any) (map[string]any, error) { +func (b *backupDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]any) (map[string]any, error) { + // Set progress percent + b.progressPercent = progress.StartedPercent + defer func() { b.progressPercent = progress.CompletedPercent }() + var ( container string err error @@ -163,6 +173,14 @@ func (*backupDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.Templa return output, nil } +func (b *backupDataUsingKopiaServerFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: b.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func backupDataUsingKopiaServer( cli kubernetes.Interface, container, diff --git a/pkg/function/checkRepository.go b/pkg/function/checkRepository.go index 88056b56e4..622ef349a5 100644 --- a/pkg/function/checkRepository.go +++ b/pkg/function/checkRepository.go @@ -3,8 +3,10 @@ package function import ( "context" "strings" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" @@ -12,6 +14,7 @@ import ( "github.com/kanisterio/kanister/pkg/consts" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -35,7 +38,9 @@ func init() { var _ kanister.Func = (*CheckRepositoryFunc)(nil) -type CheckRepositoryFunc struct{} +type CheckRepositoryFunc struct { + progressPercent string +} func (*CheckRepositoryFunc) Name() string { return CheckRepositoryFuncName @@ -115,7 +120,11 @@ func CheckRepositoryPodFunc( } } -func (*CheckRepositoryFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (c *CheckRepositoryFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + c.progressPercent = progress.StartedPercent + defer func() { c.progressPercent = progress.CompletedPercent }() + var checkRepositoryArtifactPrefix, encryptionKey string if err := Arg(args, CheckRepositoryArtifactPrefixArg, &checkRepositoryArtifactPrefix); err != nil { return nil, err @@ -151,3 +160,10 @@ func (*CheckRepositoryFunc) Arguments() []string { CheckRepositoryEncryptionKeyArg, } } +func (c *CheckRepositoryFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: c.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/copy_volume_data.go b/pkg/function/copy_volume_data.go index f96ebd2913..f41041bbf5 100644 --- a/pkg/function/copy_volume_data.go +++ b/pkg/function/copy_volume_data.go @@ -18,6 +18,7 @@ import ( "bytes" "context" "fmt" + "time" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -25,11 +26,13 @@ import ( "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/consts" "github.com/kanisterio/kanister/pkg/format" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -58,7 +61,9 @@ func init() { var _ kanister.Func = (*copyVolumeDataFunc)(nil) -type copyVolumeDataFunc struct{} +type copyVolumeDataFunc struct { + progressPercent string +} func (*copyVolumeDataFunc) Name() string { return CopyVolumeDataFuncName @@ -158,7 +163,11 @@ func copyVolumeDataPodFunc( } } -func (*copyVolumeDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (c *copyVolumeDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + c.progressPercent = progress.StartedPercent + defer func() { c.progressPercent = progress.CompletedPercent }() + var namespace, vol, targetPath, encryptionKey string var err error if err = Arg(args, CopyVolumeDataNamespaceArg, &namespace); err != nil { @@ -207,3 +216,11 @@ func (*copyVolumeDataFunc) Arguments() []string { CopyVolumeDataEncryptionKeyArg, } } + +func (c *copyVolumeDataFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: c.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/create_csi_snapshot.go b/pkg/function/create_csi_snapshot.go index abcf9bb58d..fde31a2c72 100644 --- a/pkg/function/create_csi_snapshot.go +++ b/pkg/function/create_csi_snapshot.go @@ -17,15 +17,19 @@ package function import ( "context" "fmt" + "time" v1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/kube/snapshot" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -55,13 +59,19 @@ const ( CreateCSISnapshotSnapshotContentNameArg = "snapshotContent" ) -type createCSISnapshotFunc struct{} +type createCSISnapshotFunc struct { + progressPercent string +} func (*createCSISnapshotFunc) Name() string { return CreateCSISnapshotFuncName } -func (*createCSISnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (c *createCSISnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + c.progressPercent = progress.StartedPercent + defer func() { c.progressPercent = progress.CompletedPercent }() + var snapshotClass string var labels map[string]string var name, pvc, namespace string @@ -147,3 +157,11 @@ func createCSISnapshot(ctx context.Context, snapshotter snapshot.Snapshotter, na func defaultSnapshotName(pvcName string, len int) string { return fmt.Sprintf("%s-snapshot-%s", pvcName, rand.String(len)) } + +func (c *createCSISnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: c.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/create_csi_snapshot_static.go b/pkg/function/create_csi_snapshot_static.go index 3ffc7401b1..d82c96142f 100644 --- a/pkg/function/create_csi_snapshot_static.go +++ b/pkg/function/create_csi_snapshot_static.go @@ -16,13 +16,17 @@ package function import ( "context" + "time" v1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/kube/snapshot" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -59,13 +63,19 @@ const ( CreateCSISnapshotStaticOutputSnapshotContentName = "snapshotContent" ) -type createCSISnapshotStaticFunc struct{} +type createCSISnapshotStaticFunc struct { + progressPercent string +} func (*createCSISnapshotStaticFunc) Name() string { return CreateCSISnapshotStaticFuncName } -func (*createCSISnapshotStaticFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (c *createCSISnapshotStaticFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + c.progressPercent = progress.StartedPercent + defer func() { c.progressPercent = progress.CompletedPercent }() + var ( name, namespace string driver, snapshotHandle, snapshotClass string @@ -158,3 +168,11 @@ func createCSISnapshotStatic( return snapshotter.Get(ctx, name, namespace) } + +func (c *createCSISnapshotStaticFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: c.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/create_rds_snapshot.go b/pkg/function/create_rds_snapshot.go index e64e9e813f..5cf40964fd 100644 --- a/pkg/function/create_rds_snapshot.go +++ b/pkg/function/create_rds_snapshot.go @@ -18,16 +18,20 @@ import ( "context" "fmt" "strconv" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" "sigs.k8s.io/yaml" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/aws/rds" "github.com/kanisterio/kanister/pkg/field" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -61,7 +65,9 @@ const ( DBEngineAuroraPostgreSQL RDSDBEngine = "aurora-postgresql" ) -type createRDSSnapshotFunc struct{} +type createRDSSnapshotFunc struct { + progressPercent string +} func (*createRDSSnapshotFunc) Name() string { return CreateRDSSnapshotFuncName @@ -155,6 +161,10 @@ func createRDSSnapshot(ctx context.Context, instanceID string, dbEngine RDSDBEng } func (crs *createRDSSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + crs.progressPercent = progress.StartedPercent + defer func() { crs.progressPercent = progress.CompletedPercent }() + var instanceID string var dbEngine RDSDBEngine if err := Arg(args, CreateRDSSnapshotInstanceIDArg, &instanceID); err != nil { @@ -180,3 +190,11 @@ func (crs *createRDSSnapshotFunc) Arguments() []string { CreateRDSSnapshotDBEngine, } } + +func (crs *createRDSSnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: crs.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/create_volume_from_snapshot.go b/pkg/function/create_volume_from_snapshot.go index d4313f3838..17c54ff3b9 100644 --- a/pkg/function/create_volume_from_snapshot.go +++ b/pkg/function/create_volume_from_snapshot.go @@ -17,12 +17,14 @@ package function import ( "context" "encoding/json" + "time" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" awsconfig "github.com/kanisterio/kanister/pkg/aws" "github.com/kanisterio/kanister/pkg/blockstorage" "github.com/kanisterio/kanister/pkg/blockstorage/getter" @@ -31,6 +33,7 @@ import ( kubevolume "github.com/kanisterio/kanister/pkg/kube/volume" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -49,7 +52,9 @@ const ( CreateVolumeFromSnapshotPVCNamesArg = "pvcNames" ) -type createVolumeFromSnapshotFunc struct{} +type createVolumeFromSnapshotFunc struct { + progressPercent string +} func (*createVolumeFromSnapshotFunc) Name() string { return CreateVolumeFromSnapshotFuncName @@ -120,7 +125,11 @@ func createVolumeFromSnapshot(ctx context.Context, cli kubernetes.Interface, nam return providerList, nil } -func (kef *createVolumeFromSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (c *createVolumeFromSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + c.progressPercent = progress.StartedPercent + defer func() { c.progressPercent = progress.CompletedPercent }() + cli, err := kube.NewClient() if err != nil { return nil, errors.Wrapf(err, "Failed to create Kubernetes client") @@ -154,3 +163,11 @@ func (*createVolumeFromSnapshotFunc) Arguments() []string { CreateVolumeFromSnapshotPVCNamesArg, } } + +func (crs *createVolumeFromSnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: crs.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/create_volume_snapshot.go b/pkg/function/create_volume_snapshot.go index 87f28684e7..a4395a6189 100644 --- a/pkg/function/create_volume_snapshot.go +++ b/pkg/function/create_volume_snapshot.go @@ -21,6 +21,7 @@ import ( "path/filepath" "strings" "sync" + "time" "github.com/pkg/errors" v1 "k8s.io/api/core/v1" @@ -35,6 +36,7 @@ import ( "github.com/kanisterio/kanister/pkg/blockstorage/getter" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/secrets" ) @@ -54,7 +56,9 @@ const ( CreateVolumeSnapshotSkipWaitArg = "skipWait" ) -type createVolumeSnapshotFunc struct{} +type createVolumeSnapshotFunc struct { + progressPercent string +} func (*createVolumeSnapshotFunc) Name() string { return CreateVolumeSnapshotFuncName @@ -261,7 +265,11 @@ func getPVCList(tp param.TemplateParams) ([]string, error) { return pvcList, nil } -func (kef *createVolumeSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (c *createVolumeSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + c.progressPercent = progress.StartedPercent + defer func() { c.progressPercent = progress.CompletedPercent }() + cli, err := kube.NewClient() if err != nil { return nil, errors.Wrapf(err, "Failed to create Kubernetes client") @@ -317,3 +325,11 @@ func (*createVolumeSnapshotFunc) Arguments() []string { CreateVolumeSnapshotSkipWaitArg, } } + +func (c *createVolumeSnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: c.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/delete_csi_snapshot.go b/pkg/function/delete_csi_snapshot.go index cbdfb3de56..4fc3e7a141 100644 --- a/pkg/function/delete_csi_snapshot.go +++ b/pkg/function/delete_csi_snapshot.go @@ -16,15 +16,19 @@ package function import ( "context" + "time" v1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/kube/snapshot" "github.com/kanisterio/kanister/pkg/param" "github.com/kanisterio/kanister/pkg/poll" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -44,13 +48,19 @@ const ( DeleteCSISnapshotNamespaceArg = "namespace" ) -type deleteCSISnapshotFunc struct{} +type deleteCSISnapshotFunc struct { + progressPercent string +} func (*deleteCSISnapshotFunc) Name() string { return DeleteCSISnapshotFuncName } -func (*deleteCSISnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (d *deleteCSISnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + d.progressPercent = progress.StartedPercent + defer func() { d.progressPercent = progress.CompletedPercent }() + var name, namespace string if err := Arg(args, DeleteCSISnapshotNameArg, &name); err != nil { return nil, err @@ -93,6 +103,14 @@ func (*deleteCSISnapshotFunc) Arguments() []string { } } +func (c *deleteCSISnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: c.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func deleteCSISnapshot(ctx context.Context, snapshotter snapshot.Snapshotter, name, namespace string) (*v1.VolumeSnapshot, error) { return snapshotter.Delete(ctx, name, namespace) } diff --git a/pkg/function/delete_csi_snapshot_content.go b/pkg/function/delete_csi_snapshot_content.go index a77a466e50..f28678a7e5 100644 --- a/pkg/function/delete_csi_snapshot_content.go +++ b/pkg/function/delete_csi_snapshot_content.go @@ -16,11 +16,15 @@ package function import ( "context" + "time" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/kube/snapshot" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func init() { @@ -39,13 +43,19 @@ const ( DeleteCSISnapshotContentNameArg = "name" ) -type deleteCSISnapshotContentFunc struct{} +type deleteCSISnapshotContentFunc struct { + progressPercent string +} func (*deleteCSISnapshotContentFunc) Name() string { return DeleteCSISnapshotContentFuncName } -func (*deleteCSISnapshotContentFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (d *deleteCSISnapshotContentFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + d.progressPercent = progress.StartedPercent + defer func() { d.progressPercent = progress.CompletedPercent }() + var name string if err := Arg(args, DeleteCSISnapshotContentNameArg, &name); err != nil { return nil, err @@ -81,6 +91,14 @@ func (*deleteCSISnapshotContentFunc) Arguments() []string { } } +func (c *deleteCSISnapshotContentFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: c.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func deleteCSISnapshotContent(ctx context.Context, snapshotter snapshot.Snapshotter, name string) error { return snapshotter.DeleteContent(ctx, name) } diff --git a/pkg/function/delete_data.go b/pkg/function/delete_data.go index 4de0951e87..fd662cfa82 100644 --- a/pkg/function/delete_data.go +++ b/pkg/function/delete_data.go @@ -19,9 +19,11 @@ import ( "context" "fmt" "strings" + "time" "github.com/pkg/errors" v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" @@ -30,6 +32,7 @@ import ( "github.com/kanisterio/kanister/pkg/format" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -61,7 +64,9 @@ func init() { var _ kanister.Func = (*deleteDataFunc)(nil) -type deleteDataFunc struct{} +type deleteDataFunc struct { + progressPercent string +} func (*deleteDataFunc) Name() string { return DeleteDataFuncName @@ -196,7 +201,11 @@ func pruneData( return spaceFreed, errors.Wrapf(err, "Failed to prune data after forget") } -func (*deleteDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (d *deleteDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + d.progressPercent = progress.StartedPercent + defer func() { d.progressPercent = progress.CompletedPercent }() + var namespace, deleteArtifactPrefix, deleteIdentifier, deleteTag, encryptionKey string var reclaimSpace bool var err error @@ -253,3 +262,11 @@ func (*deleteDataFunc) Arguments() []string { DeleteDataReclaimSpace, } } + +func (d *deleteDataFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/delete_data_all.go b/pkg/function/delete_data_all.go index 2b6fd8e054..1e631e5bd1 100644 --- a/pkg/function/delete_data_all.go +++ b/pkg/function/delete_data_all.go @@ -18,12 +18,16 @@ import ( "context" "encoding/json" "fmt" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -51,13 +55,19 @@ func init() { var _ kanister.Func = (*deleteDataAllFunc)(nil) -type deleteDataAllFunc struct{} +type deleteDataAllFunc struct { + progressPercent string +} func (*deleteDataAllFunc) Name() string { return DeleteDataAllFuncName } -func (*deleteDataAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (d *deleteDataAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + d.progressPercent = progress.StartedPercent + defer func() { d.progressPercent = progress.CompletedPercent }() + var namespace, deleteArtifactPrefix, backupInfo, encryptionKey string var reclaimSpace bool var err error @@ -120,3 +130,11 @@ func (*deleteDataAllFunc) Arguments() []string { DeleteDataAllReclaimSpace, } } + +func (d *deleteDataAllFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/delete_data_using_kopia_server.go b/pkg/function/delete_data_using_kopia_server.go index f23c068815..74d97db565 100644 --- a/pkg/function/delete_data_using_kopia_server.go +++ b/pkg/function/delete_data_using_kopia_server.go @@ -17,23 +17,29 @@ package function import ( "bytes" "context" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/format" kankopia "github.com/kanisterio/kanister/pkg/kopia" kopiacmd "github.com/kanisterio/kanister/pkg/kopia/command" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( DeleteDataUsingKopiaServerFuncName = "DeleteDataUsingKopiaServer" ) -type deleteDataUsingKopiaServerFunc struct{} +type deleteDataUsingKopiaServerFunc struct { + progressPercent string +} func init() { err := kanister.Register(&deleteDataUsingKopiaServerFunc{}) @@ -65,7 +71,11 @@ func (*deleteDataUsingKopiaServerFunc) Arguments() []string { } } -func (*deleteDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]any) (map[string]any, error) { +func (d *deleteDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]any) (map[string]any, error) { + // Set progress percent + d.progressPercent = progress.StartedPercent + defer func() { d.progressPercent = progress.CompletedPercent }() + var ( err error image string @@ -121,6 +131,14 @@ func (*deleteDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.Templa ) } +func (d *deleteDataUsingKopiaServerFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func deleteDataFromServer( ctx context.Context, cli kubernetes.Interface, diff --git a/pkg/function/delete_rds_snapshot.go b/pkg/function/delete_rds_snapshot.go index f1b008337a..2c0f5412d9 100644 --- a/pkg/function/delete_rds_snapshot.go +++ b/pkg/function/delete_rds_snapshot.go @@ -16,16 +16,20 @@ package function import ( "context" + "time" "github.com/aws/aws-sdk-go/aws/awserr" awsrds "github.com/aws/aws-sdk-go/service/rds" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/aws/rds" "github.com/kanisterio/kanister/pkg/field" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -42,7 +46,9 @@ const ( DeleteRDSSnapshotSnapshotIDArg = "snapshotID" ) -type deleteRDSSnapshotFunc struct{} +type deleteRDSSnapshotFunc struct { + progressPercent string +} func (*deleteRDSSnapshotFunc) Name() string { return DeleteRDSSnapshotFuncName @@ -109,6 +115,10 @@ func deleteRDSSnapshot(ctx context.Context, snapshotID string, profile *param.Pr } func (crs *deleteRDSSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + crs.progressPercent = progress.StartedPercent + defer func() { crs.progressPercent = progress.CompletedPercent }() + var snapshotID string var dbEngine RDSDBEngine if err := Arg(args, DeleteRDSSnapshotSnapshotIDArg, &snapshotID); err != nil { @@ -132,3 +142,11 @@ func (*deleteRDSSnapshotFunc) Arguments() []string { CreateRDSSnapshotDBEngine, } } + +func (d *deleteRDSSnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/delete_volume_snapshot.go b/pkg/function/delete_volume_snapshot.go index 2abc3eecf4..7e1cc4fbc2 100644 --- a/pkg/function/delete_volume_snapshot.go +++ b/pkg/function/delete_volume_snapshot.go @@ -18,11 +18,14 @@ import ( "context" "encoding/json" "strings" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" awsconfig "github.com/kanisterio/kanister/pkg/aws" "github.com/kanisterio/kanister/pkg/blockstorage" "github.com/kanisterio/kanister/pkg/blockstorage/getter" @@ -30,6 +33,7 @@ import ( "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -48,7 +52,9 @@ const ( SnapshotDoesNotExistError = "does not exist" ) -type deleteVolumeSnapshotFunc struct{} +type deleteVolumeSnapshotFunc struct { + progressPercent string +} func (*deleteVolumeSnapshotFunc) Name() string { return DeleteVolumeSnapshotFuncName @@ -93,7 +99,11 @@ func deleteVolumeSnapshot(ctx context.Context, cli kubernetes.Interface, namespa return providerList, nil } -func (kef *deleteVolumeSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (d *deleteVolumeSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + d.progressPercent = progress.StartedPercent + defer func() { d.progressPercent = progress.CompletedPercent }() + cli, err := kube.NewClient() if err != nil { return nil, errors.Wrapf(err, "Failed to create Kubernetes client") @@ -122,3 +132,11 @@ func (*deleteVolumeSnapshotFunc) Arguments() []string { DeleteVolumeSnapshotManifestArg, } } + +func (d *deleteVolumeSnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/describe_backups.go b/pkg/function/describe_backups.go index fb9f512a13..841b00d554 100644 --- a/pkg/function/describe_backups.go +++ b/pkg/function/describe_backups.go @@ -18,8 +18,10 @@ import ( "bytes" "context" "strings" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" @@ -28,6 +30,7 @@ import ( "github.com/kanisterio/kanister/pkg/format" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -54,7 +57,9 @@ func init() { var _ kanister.Func = (*DescribeBackupsFunc)(nil) -type DescribeBackupsFunc struct{} +type DescribeBackupsFunc struct { + progressPercent string +} func (*DescribeBackupsFunc) Name() string { return DescribeBackupsFuncName @@ -167,7 +172,11 @@ func describeBackupsPodFunc( } } -func (*DescribeBackupsFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (d *DescribeBackupsFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + d.progressPercent = progress.StartedPercent + defer func() { d.progressPercent = progress.CompletedPercent }() + var describeBackupsArtifactPrefix, encryptionKey string var err error if err = Arg(args, DescribeBackupsArtifactPrefixArg, &describeBackupsArtifactPrefix); err != nil { @@ -204,3 +213,11 @@ func (*DescribeBackupsFunc) Arguments() []string { DescribeBackupsEncryptionKeyArg, } } + +func (d *DescribeBackupsFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/export_rds_snapshot_location.go b/pkg/function/export_rds_snapshot_location.go index fbab481db2..f94e58eecf 100644 --- a/pkg/function/export_rds_snapshot_location.go +++ b/pkg/function/export_rds_snapshot_location.go @@ -19,8 +19,10 @@ import ( "encoding/json" "fmt" "strings" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" "sigs.k8s.io/yaml" @@ -32,6 +34,7 @@ import ( "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" "github.com/kanisterio/kanister/pkg/postgres" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -64,7 +67,9 @@ const ( postgresToolsImage = "ghcr.io/kanisterio/postgres-kanister-tools:0.96.0" ) -type exportRDSSnapshotToLocationFunc struct{} +type exportRDSSnapshotToLocationFunc struct { + progressPercent string +} // RDSDBEngine for RDS Engine types type RDSDBEngine string @@ -151,6 +156,10 @@ func exportRDSSnapshotToLoc(ctx context.Context, namespace, instanceID, snapshot } func (crs *exportRDSSnapshotToLocationFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + crs.progressPercent = progress.StartedPercent + defer func() { crs.progressPercent = progress.CompletedPercent }() + var namespace, instanceID, snapshotID, username, password, dbSubnetGroup, backupArtifact string var dbEngine RDSDBEngine @@ -217,6 +226,14 @@ func (*exportRDSSnapshotToLocationFunc) Arguments() []string { } } +func (d *exportRDSSnapshotToLocationFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func execDumpCommand(ctx context.Context, dbEngine RDSDBEngine, action RDSAction, namespace, dbEndpoint, username, password string, databases []string, backupPrefix, backupID string, profile *param.Profile, dbEngineVersion string) (map[string]interface{}, error) { // Trim "\n" from creds username = strings.TrimSpace(username) diff --git a/pkg/function/kube_exec.go b/pkg/function/kube_exec.go index 09fd38abc7..ab47058a0b 100644 --- a/pkg/function/kube_exec.go +++ b/pkg/function/kube_exec.go @@ -20,11 +20,15 @@ import ( "io" "os" "regexp" + "time" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/output" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func init() { @@ -44,7 +48,9 @@ const ( KubeExecCommandArg = "command" ) -type kubeExecFunc struct{} +type kubeExecFunc struct { + progressPercent string +} func (*kubeExecFunc) Name() string { return KubeExecFuncName @@ -73,6 +79,10 @@ func parseLogAndCreateOutput(out string) (map[string]interface{}, error) { } func (kef *kubeExecFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + kef.progressPercent = progress.StartedPercent + defer func() { kef.progressPercent = progress.CompletedPercent }() + cli, err := kube.NewClient() if err != nil { return nil, err @@ -119,3 +129,11 @@ func (*kubeExecFunc) Arguments() []string { KubeExecContainerNameArg, } } + +func (kef *kubeExecFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: kef.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/kube_exec_all.go b/pkg/function/kube_exec_all.go index 144e2dda79..6e7b52246c 100644 --- a/pkg/function/kube_exec_all.go +++ b/pkg/function/kube_exec_all.go @@ -17,14 +17,18 @@ package function import ( "context" "strings" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/format" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -44,13 +48,19 @@ const ( KubeExecAllCommandArg = "command" ) -type kubeExecAllFunc struct{} +type kubeExecAllFunc struct { + progressPercent string +} func (*kubeExecAllFunc) Name() string { return KubeExecAllFuncName } -func (*kubeExecAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (kef *kubeExecAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + kef.progressPercent = progress.StartedPercent + defer func() { kef.progressPercent = progress.CompletedPercent }() + cli, err := kube.NewClient() if err != nil { return nil, err @@ -92,6 +102,14 @@ func (*kubeExecAllFunc) Arguments() []string { } } +func (k *kubeExecAllFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: k.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func execAll(ctx context.Context, cli kubernetes.Interface, namespace string, ps []string, cs []string, cmd []string) (map[string]interface{}, error) { numContainers := len(ps) * len(cs) errChan := make(chan error, numContainers) diff --git a/pkg/function/kube_task.go b/pkg/function/kube_task.go index b30dcb512e..0b671cd00a 100644 --- a/pkg/function/kube_task.go +++ b/pkg/function/kube_task.go @@ -16,8 +16,10 @@ package function import ( "context" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" @@ -27,6 +29,7 @@ import ( "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/output" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( @@ -45,7 +48,9 @@ func init() { var _ kanister.Func = (*kubeTaskFunc)(nil) -type kubeTaskFunc struct{} +type kubeTaskFunc struct { + progressPercent string +} func (*kubeTaskFunc) Name() string { return KubeTaskFuncName @@ -89,6 +94,10 @@ func kubeTaskPodFunc() func(ctx context.Context, pc kube.PodController) (map[str } func (ktf *kubeTaskFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + ktf.progressPercent = progress.StartedPercent + defer func() { ktf.progressPercent = progress.CompletedPercent }() + var namespace, image string var command []string var err error @@ -128,3 +137,11 @@ func (*kubeTaskFunc) Arguments() []string { KubeTaskPodOverrideArg, } } + +func (k *kubeTaskFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: k.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/kubeops.go b/pkg/function/kubeops.go index 5fd901ae79..39cfa6c57a 100644 --- a/pkg/function/kubeops.go +++ b/pkg/function/kubeops.go @@ -19,6 +19,7 @@ import ( "encoding/json" "fmt" "strings" + "time" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -28,6 +29,7 @@ import ( crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -51,13 +53,19 @@ const ( KubeOpsOperationArg = "operation" ) -type kubeops struct{} +type kubeops struct { + progressPercent string +} func (*kubeops) Name() string { return KubeOpsFuncName } -func (crs *kubeops) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (k *kubeops) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + k.progressPercent = progress.StartedPercent + defer func() { k.progressPercent = progress.CompletedPercent }() + var spec, namespace string var op kube.Operation var objRefArg crv1alpha1.ObjectReference @@ -128,3 +136,11 @@ func (*kubeops) Arguments() []string { KubeOpsObjectReferenceArg, } } + +func (k *kubeops) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: k.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/location_delete.go b/pkg/function/location_delete.go index 1977b7fa04..0a3cdc079c 100644 --- a/pkg/function/location_delete.go +++ b/pkg/function/location_delete.go @@ -17,12 +17,16 @@ package function import ( "context" "strings" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/location" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( @@ -38,13 +42,19 @@ func init() { var _ kanister.Func = (*locationDeleteFunc)(nil) -type locationDeleteFunc struct{} +type locationDeleteFunc struct { + progressPercent string +} func (*locationDeleteFunc) Name() string { return LocationDeleteFuncName } -func (*locationDeleteFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (l *locationDeleteFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + l.progressPercent = progress.StartedPercent + defer func() { l.progressPercent = progress.CompletedPercent }() + var artifact string var err error if err = Arg(args, LocationDeleteArtifactArg, &artifact); err != nil { @@ -63,3 +73,11 @@ func (*locationDeleteFunc) RequiredArgs() []string { func (*locationDeleteFunc) Arguments() []string { return []string{LocationDeleteArtifactArg} } + +func (l *locationDeleteFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: l.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/prepare_data.go b/pkg/function/prepare_data.go index 37c5544b20..657407b59f 100644 --- a/pkg/function/prepare_data.go +++ b/pkg/function/prepare_data.go @@ -18,6 +18,7 @@ import ( "context" "fmt" "io" + "time" "github.com/kanisterio/kanister/pkg/consts" "github.com/kanisterio/kanister/pkg/field" @@ -30,6 +31,7 @@ import ( "github.com/kanisterio/kanister/pkg/format" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( @@ -51,7 +53,9 @@ func init() { var _ kanister.Func = (*prepareDataFunc)(nil) -type prepareDataFunc struct{} +type prepareDataFunc struct { + progressPercent string +} func (*prepareDataFunc) Name() string { return PrepareDataFuncName @@ -129,7 +133,11 @@ func prepareDataPodFunc(cli kubernetes.Interface) func(ctx context.Context, pc k } } -func (*prepareDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (p *prepareDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + p.progressPercent = progress.StartedPercent + defer func() { p.progressPercent = progress.CompletedPercent }() + var namespace, image, serviceAccount string var command []string var vols map[string]string @@ -184,3 +192,11 @@ func (*prepareDataFunc) Arguments() []string { PrepareDataPodOverrideArg, } } + +func (p *prepareDataFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: p.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/restore_csi_snapshot.go b/pkg/function/restore_csi_snapshot.go index 6196944a5d..c3a140f97a 100644 --- a/pkg/function/restore_csi_snapshot.go +++ b/pkg/function/restore_csi_snapshot.go @@ -18,6 +18,7 @@ import ( "context" "errors" "fmt" + "time" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -25,8 +26,10 @@ import ( "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -60,7 +63,9 @@ const ( RestoreCSISnapshotVolumeModeArg = "volumeMode" ) -type restoreCSISnapshotFunc struct{} +type restoreCSISnapshotFunc struct { + progressPercent string +} type restoreCSISnapshotArgs struct { Name string @@ -77,7 +82,11 @@ func (*restoreCSISnapshotFunc) Name() string { return RestoreCSISnapshotFuncName } -func (*restoreCSISnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (r *restoreCSISnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + r.progressPercent = progress.StartedPercent + defer func() { r.progressPercent = progress.CompletedPercent }() + var restoreSize string var restoreArgs restoreCSISnapshotArgs if err := Arg(args, RestoreCSISnapshotNameArg, &restoreArgs.Name); err != nil { @@ -152,6 +161,14 @@ func (*restoreCSISnapshotFunc) Arguments() []string { } } +func (d *restoreCSISnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func getClient() (kubernetes.Interface, error) { kubeCli, err := kube.NewClient() return kubeCli, err diff --git a/pkg/function/restore_data.go b/pkg/function/restore_data.go index ad54550c1f..747a322dd4 100644 --- a/pkg/function/restore_data.go +++ b/pkg/function/restore_data.go @@ -17,6 +17,7 @@ package function import ( "bytes" "context" + "time" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -27,6 +28,7 @@ import ( "github.com/kanisterio/kanister/pkg/format" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -62,7 +64,9 @@ func init() { var _ kanister.Func = (*restoreDataFunc)(nil) -type restoreDataFunc struct{} +type restoreDataFunc struct { + progressPercent string +} func (*restoreDataFunc) Name() string { return RestoreDataFuncName @@ -180,7 +184,11 @@ func restoreDataPodFunc( } } -func (*restoreDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (r *restoreDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + r.progressPercent = progress.StartedPercent + defer func() { r.progressPercent = progress.CompletedPercent }() + var namespace, image, backupArtifactPrefix, backupTag, backupID string var podOverride crv1alpha1.JSONMap var err error @@ -254,3 +262,11 @@ func (*restoreDataFunc) Arguments() []string { RestoreDataPodOverrideArg, } } + +func (d *restoreDataFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/restore_data_all.go b/pkg/function/restore_data_all.go index dd6fb967a9..31a2c626f1 100644 --- a/pkg/function/restore_data_all.go +++ b/pkg/function/restore_data_all.go @@ -19,13 +19,16 @@ import ( "encoding/json" "fmt" "strings" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -57,7 +60,9 @@ func init() { var _ kanister.Func = (*restoreDataAllFunc)(nil) -type restoreDataAllFunc struct{} +type restoreDataAllFunc struct { + progressPercent string +} func (*restoreDataAllFunc) Name() string { return RestoreDataAllFuncName @@ -99,7 +104,11 @@ func validateAndGetRestoreAllOptArgs(args map[string]interface{}, tp param.Templ return restorePath, encryptionKey, ps, podOverride, nil } -func (*restoreDataAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (r *restoreDataAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + r.progressPercent = progress.StartedPercent + defer func() { r.progressPercent = progress.CompletedPercent }() + var namespace, image, backupArtifactPrefix, backupInfo string var err error if err = Arg(args, RestoreDataAllNamespaceArg, &namespace); err != nil { @@ -190,3 +199,11 @@ func (*restoreDataAllFunc) Arguments() []string { RestoreDataAllPodOverrideArg, } } + +func (r *restoreDataAllFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: r.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/restore_data_using_kopia_server.go b/pkg/function/restore_data_using_kopia_server.go index 0d327fd5a0..f4b906a12f 100644 --- a/pkg/function/restore_data_using_kopia_server.go +++ b/pkg/function/restore_data_using_kopia_server.go @@ -18,6 +18,7 @@ import ( "bytes" "context" "fmt" + "time" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -30,6 +31,7 @@ import ( kopiacmd "github.com/kanisterio/kanister/pkg/kopia/command" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( @@ -38,7 +40,9 @@ const ( SparseRestoreOption = "sparseRestore" ) -type restoreDataUsingKopiaServerFunc struct{} +type restoreDataUsingKopiaServerFunc struct { + progressPercent string +} func init() { _ = kanister.Register(&restoreDataUsingKopiaServerFunc{}) @@ -72,7 +76,11 @@ func (*restoreDataUsingKopiaServerFunc) Arguments() []string { } } -func (*restoreDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]any) (map[string]any, error) { +func (r *restoreDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]any) (map[string]any, error) { + // Set progress percent + r.progressPercent = progress.StartedPercent + defer func() { r.progressPercent = progress.CompletedPercent }() + var ( err error image string @@ -151,6 +159,14 @@ func (*restoreDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.Templ ) } +func (r *restoreDataUsingKopiaServerFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: r.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func restoreDataFromServer( ctx context.Context, cli kubernetes.Interface, diff --git a/pkg/function/restore_rds_snapshot.go b/pkg/function/restore_rds_snapshot.go index 6d0afb6fb8..bec1e357eb 100644 --- a/pkg/function/restore_rds_snapshot.go +++ b/pkg/function/restore_rds_snapshot.go @@ -17,19 +17,23 @@ package function import ( "context" "fmt" + "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" rdserr "github.com/aws/aws-sdk-go/service/rds" "github.com/hashicorp/go-version" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/aws/rds" "github.com/kanisterio/kanister/pkg/field" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" "github.com/kanisterio/kanister/pkg/postgres" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -74,7 +78,9 @@ const ( RDSPostgresDBInstanceEngineVersion = "13.0" ) -type restoreRDSSnapshotFunc struct{} +type restoreRDSSnapshotFunc struct { + progressPercent string +} func (*restoreRDSSnapshotFunc) Name() string { return RestoreRDSSnapshotFuncName @@ -99,7 +105,11 @@ func (*restoreRDSSnapshotFunc) Arguments() []string { } } -func (*restoreRDSSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (r *restoreRDSSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + r.progressPercent = progress.StartedPercent + defer func() { r.progressPercent = progress.CompletedPercent }() + var namespace, instanceID, subnetGroup, snapshotID, backupArtifactPrefix, backupID, username, password string var dbEngine RDSDBEngine @@ -146,6 +156,14 @@ func (*restoreRDSSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams return restoreRDSSnapshot(ctx, namespace, instanceID, subnetGroup, snapshotID, backupArtifactPrefix, backupID, username, password, dbEngine, sgIDs, tp.Profile) } +func (r *restoreRDSSnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: r.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func restoreRDSSnapshot(ctx context.Context, namespace, instanceID, subnetGroup, snapshotID, backupArtifactPrefix, backupID, username, password string, dbEngine RDSDBEngine, sgIDs []string, profile *param.Profile) (map[string]interface{}, error) { // Validate profile if err := ValidateProfile(profile); err != nil { diff --git a/pkg/function/scale_workload.go b/pkg/function/scale_workload.go index 673a4fe4e8..9d6de8ec0e 100644 --- a/pkg/function/scale_workload.go +++ b/pkg/function/scale_workload.go @@ -18,14 +18,18 @@ import ( "context" "strconv" "strings" + "time" osversioned "github.com/openshift/client-go/apps/clientset/versioned" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( @@ -46,13 +50,19 @@ var ( _ kanister.Func = (*scaleWorkloadFunc)(nil) ) -type scaleWorkloadFunc struct{} +type scaleWorkloadFunc struct { + progressPercent string +} func (*scaleWorkloadFunc) Name() string { return ScaleWorkloadFuncName } -func (*scaleWorkloadFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (s *scaleWorkloadFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + s.progressPercent = progress.StartedPercent + defer func() { s.progressPercent = progress.CompletedPercent }() + var namespace, kind, name string var replicas int32 namespace, kind, name, replicas, waitForReady, err := getArgs(tp, args) @@ -97,6 +107,14 @@ func (*scaleWorkloadFunc) Arguments() []string { } } +func (s *scaleWorkloadFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: s.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func getArgs(tp param.TemplateParams, args map[string]interface{}) (namespace, kind, name string, replicas int32, waitForReady bool, err error) { var rep interface{} waitForReady = true diff --git a/pkg/function/wait.go b/pkg/function/wait.go index e5e3e9d3d7..3d291db7dd 100644 --- a/pkg/function/wait.go +++ b/pkg/function/wait.go @@ -37,6 +37,7 @@ import ( "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" "github.com/kanisterio/kanister/pkg/poll" + "github.com/kanisterio/kanister/pkg/progress" ) type WaitConditions struct { @@ -62,13 +63,19 @@ func init() { var _ kanister.Func = (*waitFunc)(nil) -type waitFunc struct{} +type waitFunc struct { + progressPercent string +} func (*waitFunc) Name() string { return WaitFuncName } -func (ktf *waitFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (w *waitFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + w.progressPercent = progress.StartedPercent + defer func() { w.progressPercent = progress.CompletedPercent }() + rendered, err := param.RenderArgs(args, tp) if err != nil { return nil, err @@ -112,6 +119,14 @@ func (*waitFunc) Arguments() []string { } } +func (w *waitFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: w.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + // waitForCondition wait till the condition satisfies within the timeout duration func waitForCondition( ctx context.Context, diff --git a/pkg/function/wait_for_snapshot_completion.go b/pkg/function/wait_for_snapshot_completion.go index 3195eb5074..c2ade04880 100644 --- a/pkg/function/wait_for_snapshot_completion.go +++ b/pkg/function/wait_for_snapshot_completion.go @@ -17,14 +17,18 @@ package function import ( "context" "encoding/json" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" awsconfig "github.com/kanisterio/kanister/pkg/aws" "github.com/kanisterio/kanister/pkg/blockstorage" "github.com/kanisterio/kanister/pkg/blockstorage/getter" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -41,7 +45,9 @@ const ( WaitForSnapshotCompletionSnapshotsArg = "snapshots" ) -type waitForSnapshotCompletionFunc struct{} +type waitForSnapshotCompletionFunc struct { + progressPercent string +} func (*waitForSnapshotCompletionFunc) Name() string { return WaitForSnapshotCompletionFuncName @@ -55,7 +61,11 @@ func (*waitForSnapshotCompletionFunc) Arguments() []string { return []string{WaitForSnapshotCompletionSnapshotsArg} } -func (kef *waitForSnapshotCompletionFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (w *waitForSnapshotCompletionFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + w.progressPercent = progress.StartedPercent + defer func() { w.progressPercent = progress.CompletedPercent }() + var snapshotinfo string if err := Arg(args, WaitForSnapshotCompletionSnapshotsArg, &snapshotinfo); err != nil { return nil, err @@ -63,6 +73,14 @@ func (kef *waitForSnapshotCompletionFunc) Exec(ctx context.Context, tp param.Tem return nil, waitForSnapshotsCompletion(ctx, snapshotinfo, tp.Profile, getter.New()) } +func (w *waitForSnapshotCompletionFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: w.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func waitForSnapshotsCompletion(ctx context.Context, snapshotinfo string, profile *param.Profile, getter getter.Getter) error { PVCData := []VolumeSnapshotInfo{} err := json.Unmarshal([]byte(snapshotinfo), &PVCData) diff --git a/pkg/function/waitv2.go b/pkg/function/waitv2.go index 88ddef5254..7912ae2a62 100644 --- a/pkg/function/waitv2.go +++ b/pkg/function/waitv2.go @@ -21,13 +21,16 @@ import ( "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/cli-runtime/pkg/printers" "k8s.io/client-go/dynamic" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( @@ -43,13 +46,19 @@ func init() { var _ kanister.Func = (*waitV2Func)(nil) -type waitV2Func struct{} +type waitV2Func struct { + progressPercent string +} func (*waitV2Func) Name() string { return WaitV2FuncName } -func (ktf *waitV2Func) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (w *waitV2Func) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + w.progressPercent = progress.StartedPercent + defer func() { w.progressPercent = progress.CompletedPercent }() + var timeout string if err := Arg(args, WaitV2TimeoutArg, &timeout); err != nil { return nil, err @@ -88,6 +97,14 @@ func (*waitV2Func) Arguments() []string { } } +func (w *waitV2Func) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: w.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + // evaluateWaitV2Condition evaluate the go template condition func evaluateWaitV2Condition(ctx context.Context, dynCli dynamic.Interface, cond Condition, tp param.TemplateParams) (bool, error) { objRef, err := resolveWaitConditionObjRefs(cond, tp) From 6603d94e38d245b33a077b9f05739dc1db2765c1 Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Wed, 27 Sep 2023 17:35:55 +0530 Subject: [PATCH 12/14] Implement ExecProgress on test function Signed-off-by: Prasad Ghangal --- pkg/blueprint/validate/validate_test.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/blueprint/validate/validate_test.go b/pkg/blueprint/validate/validate_test.go index c7382caff2..c22ee38c17 100644 --- a/pkg/blueprint/validate/validate_test.go +++ b/pkg/blueprint/validate/validate_test.go @@ -438,7 +438,9 @@ func blueprint() *crv1alpha1.Blueprint { } } -type nonDefaultVersionFunc struct{} +type nonDefaultVersionFunc struct { + progressPercent string +} func (nd *nonDefaultVersionFunc) Name() string { return "NonDefaultVersionFunc" @@ -453,9 +455,15 @@ func (nd *nonDefaultVersionFunc) Arguments() []string { } func (nd *nonDefaultVersionFunc) Exec(context.Context, param.TemplateParams, map[string]interface{}) (map[string]interface{}, error) { + nd.progressPercent = "0" + defer func() { nd.progressPercent = "100" }() return nil, nil } +func (nd *nonDefaultVersionFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + return crv1alpha1.PhaseProgress{ProgressPercent: nd.progressPercent}, nil +} + var _ kanister.Func = (*nonDefaultVersionFunc)(nil) func init() { From d1aa60fd8411495a8f5e28ea116e692bee053e33 Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Wed, 27 Sep 2023 17:36:35 +0530 Subject: [PATCH 13/14] Remove unused mockPhase in test Signed-off-by: Prasad Ghangal --- pkg/progress/action_single_phase_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/progress/action_single_phase_test.go b/pkg/progress/action_single_phase_test.go index cfbc9b3d97..8a843779e9 100644 --- a/pkg/progress/action_single_phase_test.go +++ b/pkg/progress/action_single_phase_test.go @@ -5,7 +5,6 @@ import ( "fmt" "testing" - kanister "github.com/kanisterio/kanister/pkg" "github.com/kanisterio/kanister/pkg/client/clientset/versioned" "github.com/kanisterio/kanister/pkg/client/clientset/versioned/fake" . "gopkg.in/check.v1" @@ -28,7 +27,6 @@ type TestSuiteSinglePhase struct { blueprint *crv1alpha1.Blueprint actionSet *crv1alpha1.ActionSet clientset *fake.Clientset - mockPhase *kanister.Phase } var _ = Suite(&TestSuiteSinglePhase{}) From 22eaade216a293db7aebaaa706461093463b85f9 Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Tue, 3 Oct 2023 12:10:47 +0530 Subject: [PATCH 14/14] Remove unnecessary whitespace in updateActionProgress func Signed-off-by: Prasad Ghangal --- pkg/progress/action.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/progress/action.go b/pkg/progress/action.go index 8e80aec06b..3cea9fcb41 100644 --- a/pkg/progress/action.go +++ b/pkg/progress/action.go @@ -73,7 +73,6 @@ func updateActionProgress( namespace string, p *kanister.Phase, ) (bool, error) { - actionSet, err := client.CrV1alpha1().ActionSets(namespace).Get(ctx, actionSetName, metav1.GetOptions{}) if err != nil { return false, errors.Wrap(err, "Failed to get actionset")