github.com/clusterize-io/tusk@v0.6.3-0.20211001020217-cfe8a8cd0d4a/runner/run.go (about) 1 package runner 2 3 import ( 4 "errors" 5 6 "github.com/clusterize-io/tusk/marshal" 7 ) 8 9 // Run defines a a single runnable item within a task. 10 type Run struct { 11 When WhenList `yaml:",omitempty"` 12 Command CommandList `yaml:",omitempty"` 13 SubTaskList SubTaskList `yaml:"task,omitempty"` 14 SetEnvironment map[string]*string `yaml:"set-environment,omitempty"` 15 16 // Computed members not specified in yaml file 17 Tasks []Task `yaml:"-"` 18 } 19 20 // UnmarshalYAML allows simple commands to represent run structs. 21 func (r *Run) UnmarshalYAML(unmarshal func(interface{}) error) error { 22 var cl CommandList 23 commandCandidate := marshal.UnmarshalCandidate{ 24 Unmarshal: func() error { return unmarshal(&cl) }, 25 Assign: func() { *r = Run{Command: cl} }, 26 } 27 28 type runType Run // Use new type to avoid recursion 29 var runItem runType 30 runCandidate := marshal.UnmarshalCandidate{ 31 Unmarshal: func() error { return unmarshal(&runItem) }, 32 Assign: func() { *r = Run(runItem) }, 33 Validate: func() error { 34 actionUsedList := []bool{ 35 len(runItem.Command) != 0, 36 len(runItem.SubTaskList) != 0, 37 runItem.SetEnvironment != nil, 38 } 39 40 count := 0 41 for _, isUsed := range actionUsedList { 42 if isUsed { 43 count++ 44 } 45 } 46 47 if count > 1 { 48 return errors.New("only one action can be defined in `run`") 49 } 50 51 return nil 52 }, 53 } 54 55 return marshal.UnmarshalOneOf(commandCandidate, runCandidate) 56 } 57 58 func (r *Run) shouldRun(ctx Context, vars map[string]string) (bool, error) { 59 if err := r.When.Validate(ctx, vars); err != nil { 60 if !IsFailedCondition(err) { 61 return false, err 62 } 63 64 for _, command := range r.Command { 65 ctx.Logger.PrintSkipped(command.Print, err.Error()) 66 } 67 68 for _, subTask := range r.SubTaskList { 69 ctx.Logger.PrintSkipped("task: "+subTask.Name, err.Error()) 70 } 71 72 return false, nil 73 } 74 75 return true, nil 76 } 77 78 // RunList is a list of run items with custom yaml unmarshaling. 79 type RunList []*Run 80 81 // UnmarshalYAML allows single items to be used as lists. 82 func (rl *RunList) UnmarshalYAML(unmarshal func(interface{}) error) error { 83 var runSlice []*Run 84 sliceCandidate := marshal.UnmarshalCandidate{ 85 Unmarshal: func() error { return unmarshal(&runSlice) }, 86 Assign: func() { *rl = runSlice }, 87 } 88 89 var runItem *Run 90 itemCandidate := marshal.UnmarshalCandidate{ 91 Unmarshal: func() error { return unmarshal(&runItem) }, 92 Assign: func() { *rl = RunList{runItem} }, 93 } 94 95 return marshal.UnmarshalOneOf(sliceCandidate, itemCandidate) 96 }