Add --resume-flag to plan run subcommand

Allows to skip phases in plan execution.

Change-Id: Iee0e0da5ae9836f27ec1810ac0d333247a6ddb8f
Signed-off-by: Ruslan Aliev <raliev@mirantis.com>
Closes: #667
This commit is contained in:
Ruslan Aliev 2021-11-10 08:24:18 +00:00
parent 4f7a9dbf6d
commit 89bd08e102
9 changed files with 31 additions and 8 deletions

View File

@ -39,7 +39,7 @@ Perform a dry run of a plan
// NewRunCommand creates a command which execute a particular phase plan
func NewRunCommand(cfgFactory config.Factory) *cobra.Command {
r := &phase.PlanRunCommand{Factory: cfgFactory}
f := &phase.RunFlags{}
f := &phase.PlanRunFlags{}
runCmd := &cobra.Command{
Use: "run PLAN_NAME",
@ -55,6 +55,8 @@ func NewRunCommand(cfgFactory config.Factory) *cobra.Command {
r.Options.DryRun = f.DryRun
case "wait-timeout":
r.Options.Timeout = &f.Timeout
case "resume-from":
r.Options.ResumeFromPhase = f.ResumeFromPhase
}
}
cmd.Flags().Visit(fn)
@ -63,6 +65,7 @@ func NewRunCommand(cfgFactory config.Factory) *cobra.Command {
}
flags := runCmd.Flags()
flags.StringVar(&f.ResumeFromPhase, "resume-from", "", "skip all phases before the specified one")
flags.BoolVar(&f.DryRun, "dry-run", false, "simulate phase execution")
flags.DurationVar(&f.Timeout, "wait-timeout", 0, "wait timeout")
return runCmd

View File

@ -16,4 +16,5 @@ Perform a dry run of a plan
Flags:
--dry-run simulate phase execution
-h, --help help for run
--resume-from string skip all phases before the specified one
--wait-timeout duration wait timeout

View File

@ -37,6 +37,7 @@ Options
--dry-run simulate phase execution
-h, --help help for run
--resume-from string skip all phases before the specified one
--wait-timeout duration wait timeout
Options inherited from parent commands

View File

@ -270,7 +270,16 @@ func (p *plan) Validate() error {
}
// Run function executes Run method for each phase
func (p *plan) Run(ro ifc.RunOptions) error {
func (p *plan) Run(ro ifc.PlanRunOptions) error {
if ro.ResumeFromPhase != "" {
for i, phase := range p.apiObj.Phases {
if phase.Name == ro.ResumeFromPhase {
p.apiObj.Phases = p.apiObj.Phases[i:]
break
}
}
}
for _, step := range p.apiObj.Phases {
phaseRunner, err := p.phaseClient.PhaseByID(ifc.ID{Name: step.Name})
if err != nil {
@ -278,7 +287,7 @@ func (p *plan) Run(ro ifc.RunOptions) error {
}
log.Printf("executing phase: %s\n", step.Name)
if err = phaseRunner.Run(ro); err != nil {
if err = phaseRunner.Run(ro.RunOptions); err != nil {
return err
}
}

View File

@ -436,7 +436,7 @@ func TestPlanRun(t *testing.T) {
require.NotNil(t, client)
p, err := client.PlanByID(tt.planID)
require.NoError(t, err)
err = p.Run(ifc.RunOptions{DryRun: true})
err = p.Run(ifc.PlanRunOptions{RunOptions: ifc.RunOptions{DryRun: true}})
if tt.errContains != "" {
require.Error(t, err)
assert.Contains(t, err.Error(), tt.errContains)

View File

@ -202,12 +202,13 @@ func (c *PlanListCommand) RunE() error {
// PlanRunFlags options for phase run command
type PlanRunFlags struct {
GenericRunFlags
ResumeFromPhase string
}
// PlanRunCommand phase run command
type PlanRunCommand struct {
PlanID ifc.ID
Options ifc.RunOptions
Options ifc.PlanRunOptions
Factory config.Factory
}

View File

@ -482,8 +482,10 @@ func TestPlanRunCommand(t *testing.T) {
tt := tc
t.Run(tt.name, func(t *testing.T) {
cmd := phase.PlanRunCommand{
Options: ifc.RunOptions{
DryRun: true,
Options: ifc.PlanRunOptions{
RunOptions: ifc.RunOptions{
DryRun: true,
},
},
Factory: tt.factory,
PlanID: tt.planID,

View File

@ -43,6 +43,12 @@ type RunOptions struct {
Timeout *time.Duration
}
// PlanRunOptions holds options for plan run method
type PlanRunOptions struct {
RunOptions
ResumeFromPhase string
}
// RenderOptions holds options for render method
type RenderOptions struct {
FilterSelector document.Selector

View File

@ -40,7 +40,7 @@ type PhaseStatus struct {
// Plan provides a way to interact with phase plans
type Plan interface {
Validate() error
Run(RunOptions) error
Run(PlanRunOptions) error
Status(StatusOptions) (PlanStatus, error)
}