diff --git a/pkg/builtin/template.go b/pkg/builtin/template.go index 1b74900..fc65c5f 100644 --- a/pkg/builtin/template.go +++ b/pkg/builtin/template.go @@ -32,6 +32,15 @@ const ( ) type ( + // Delims are the delimiters to use to escape template functions. + Delims struct { + // Left is the opening delimiter + Left string `mapstructure:"left"` + + // Right is the closing delimiter + Right string `mapstructure:"right"` + } + // Template is a task to expand the input file using // the Template file. Output is written to the redirected STDOUT // Delims is used to change the standard golang templatiing delimiters @@ -44,7 +53,7 @@ type ( // Delims are the delimiters used to identify template script. // Leave blank for the default go templating delimiters - Delims rocket.Delims `mapstructure:"delims"` + Delims Delims `mapstructure:"delims"` } templateType struct{} diff --git a/pkg/rocket/capcomm.go b/pkg/rocket/capcomm.go index 6b93248..efecf63 100644 --- a/pkg/rocket/capcomm.go +++ b/pkg/rocket/capcomm.go @@ -319,6 +319,15 @@ func (capComm *CapComm) ExportVariable(key, value string) *CapComm { return capComm } +// ExportVariables exports a list of variables if set in the capComm to aa parent. +func (capComm *CapComm) ExportVariables(exports Exports) { + for _, key := range exports { + if value, ok := capComm.variables[key]; ok { + capComm.exportTo[key] = value + } + } +} + // WithMission attaches the mission to the CapComm. func (capComm *CapComm) WithMission(mission *Mission) *CapComm { capComm.mustNotBeSealed() diff --git a/pkg/rocket/mission.go b/pkg/rocket/mission.go index d0ea4ef..6a93475 100644 --- a/pkg/rocket/mission.go +++ b/pkg/rocket/mission.go @@ -82,8 +82,11 @@ type ( // The list is checked prior too processing the activities own set of param definitions. MustHaveParams []string + // Exports is a list of exported variables from on task context to another + Exports []string + // Stages is a slice of stages. - Stages []*Stage + Stages []Stage // Tasks is a slice of tasks Tasks []Task @@ -150,20 +153,20 @@ type ( // They are not template expanded BasicEnv EnvMap `mapstructure:"basicEnv"` - // Dir is the directory to execute the stage in + // Dir is the directory to execute the stage in. Dir string `mapstructure:"dir"` // Env is a map of additional environment variables - // These are subject to template expansion after the params have been expanded + // These are subject to template expansion after the params have been expanded. Env EnvMap `mapstructure:"env"` - // Filter is an optional filter on the stage - // If the filter criteria are not met the stage will not be executed + // Filter is an optional filter on the stage. + // If the filter criteria are not met the stage will not be executed. Filter *Filter `mapstructure:"filter"` - // NoTrust indicates the stage should not inherit environment + // NoTrust indicates the stage should not inherit environment. // variables or parameters from its parent. This can be used with a run stage - // where you do not want the process to receive API tokens etc + // where you do not want the process to receive API tokens etc. NoTrust bool `mapstructure:"noTrust"` // Must is a slice of params that must be defined prior to the stage starting @@ -181,9 +184,6 @@ type ( // OnFail is a task that is executed if the stage fails. OnFail *Task `mapstructure:"onfail"` - - // Try to run the stage but if it fails do no abort the whole run - Try string `mapstructure:"try"` } // Task is an activity that is executed. @@ -205,24 +205,24 @@ type ( // Definition contains the additional data required to process the task type Definition map[string]interface{} `mapstructure:",remain"` - // BasicEnv is a map of additional environment variables - // They are not template expanded + // BasicEnv is a map of additional environment variables. + // They are not template expanded. BasicEnv EnvMap `mapstructure:"basicEnv"` - // Dir is the directory to execute the task in + // Dir is the directory to execute the task within. Dir string `mapstructure:"dir"` - // Env is a map of additional environment variables - // These are subject to template expansion after the params have been expanded + // Env is a map of additional environment variables. + // These are subject to template expansion after the params have been expanded. Env EnvMap `mapstructure:"env"` - // Filter is an optional filter on the task - // If the filter criteria are not met the task will not be executed + // Filter is an optional filter on the task. + // If the filter criteria are not met the task will not be executed. Filter *Filter `mapstructure:"filter"` // NoTrust indicates the task should not inherit environment // variables or parameters from the parent. This can be used with a run task - // where you do not want the process to receive API tokens etc + // where you do not want the process to receive API tokens etc. NoTrust bool `mapstructure:"noTrust"` // Must is a slice of params that must be defined prior to the task starting @@ -231,27 +231,37 @@ type ( // Params is a collection of parameters that can be used within // the child stages. Parameters are template expanded and can use - // Environment variables defined in Env + // Environment variables defined in Env. Params Params `mapstructure:"params"` - // Try to run the task but if it fails do no abort the whole run - Try string `mapstructure:"try"` + // Try is a list of tasks to try. + Try Tasks `mapstructure:"try"` + + // Try is a list of tasks to try. + Group Tasks `mapstructure:"group"` + + // OnFail is a task that is executed if the stage fails. + OnFail *Task `mapstructure:"onfail"` + + // Export is a list of variables to export. This list can be used by try and group task types + // to export their variables (output from sub tasks) to their parent stage or task. + Export Exports `mapstructure:"export"` } // Filter restricts running an activity // The filter applis to the OS and Architecture of the machine running // rocket. This allows OS specific scripts to be used. Filter struct { - // IncludeOS is a list of operating systems to include + // IncludeOS is a list of operating systems to include. IncludeOS []string `mapstructure:"includeOS"` - // IncludeArch is a list of architectures to permit + // IncludeArch is a list of architectures to permit. IncludeArch []string `mapstructure:"includeArch"` - // ExcludeOS restricts an operating system from running + // ExcludeOS restricts an operating system from running. ExcludeOS []string `mapstructure:"excludeOS"` - // ExcludeArch restricts specific architectures from running + // ExcludeArch restricts specific architectures from running. ExcludeArch []string `mapstructure:"excludeArch"` // Skip prevents theactivity from running if true. @@ -261,13 +271,13 @@ type ( // OutputSpec defines the method of outputtting for a given resource. The choice is // either variables or files. OutputSpec struct { - // Variable is an exported variable available to later tasks in the same stage + // Variable is an exported variable available to later tasks in the same stage. Variable string `mapstructure:"variable"` - // Output is a path to a file replacing STDOUT + // Output is a path to a file replacing STDOUT. Path string `mapstructure:"path"` - // AppendOutput specifies if output should append + // AppendOutput specifies if output should append. Append bool `mapstructure:"append"` // SkipExpand when true skips template expansion of the runbook. @@ -280,7 +290,7 @@ type ( // InputSpec is a resource input specificsation. Input data can be provided from // inline valuses, exported stage variables, local files or a web url. InputSpec struct { - // Variable name to import from + // Variable name to import from. Variable string `mapstructure:"variable"` Inline string `mapstructure:"inline"` @@ -325,15 +335,6 @@ type ( // When DirectError is false std error output is logged. DirectError bool `mapstructure:"directStdErr"` } - - // Delims are the delimiters to use to escape template functions. - Delims struct { - // Left is the opening delimiter - Left string `mapstructure:"left"` - - // Right is the closing delimiter - Right string `mapstructure:"right"` - } ) // Validate checks that include has one and only one resource identifier defined. @@ -371,6 +372,13 @@ func (params MustHaveParams) Copy() MustHaveParams { return c } +// Copy copies the must have params. +func (exports Exports) Copy() Exports { + c := make(Exports, len(exports)) + copy(c, exports) + return c +} + // Copy the params. func (params Params) Copy() Params { c := make(Params, len(params)) @@ -391,7 +399,7 @@ func (tasks Tasks) ToMap() TaskMap { for _, v := range tasks { if v.Name != "" { - c[v.Name] = &v + c[v.Name] = v } } diff --git a/pkg/rocket/missioncontrol.go b/pkg/rocket/missioncontrol.go index 2bf6331..2755645 100644 --- a/pkg/rocket/missioncontrol.go +++ b/pkg/rocket/missioncontrol.go @@ -36,6 +36,15 @@ var ( defaultControl MissionController ) +type taskKind int + +const ( + taskKindNone = taskKind(iota) + taskKindType + taskKindTry + taskKindGroup +) + type ( // Option is the interface supported by all mission options. @@ -47,10 +56,10 @@ type ( ExecuteFunc = loggee.ActivityFunc // Stage map is a map of stage names to stages - StageMap map[string]*Stage + StageMap map[string]Stage // TaskMap maps the task name to the task. - TaskMap map[string]*Task + TaskMap map[string]Task // TaskType represents a specific task type. TaskType interface { @@ -208,7 +217,7 @@ func (mc *missionControl) LaunchMissionWithParams(ctx context.Context, location var fallbackOp *operation if mission.OnFail != nil { - fallbackOp, err = mc.prepareFailStage(ctx, capComm, stageMap, mission.OnFail) + fallbackOp, err = mc.prepareFailStage(ctx, capComm, stageMap, *mission.OnFail) if err != nil { return err } @@ -223,8 +232,8 @@ func mergeStages(stage *Stage, ref string, stageMap StageMap, circular map[strin } circular[ref] = true - src := stageMap[ref] - if src == nil { + src, ok := stageMap[ref] + if !ok { return fmt.Errorf("unknown stage ref %s", ref) } @@ -237,10 +246,6 @@ func mergeStages(stage *Stage, ref string, stageMap StageMap, circular map[strin stage.Dir = src.Dir } - if stage.Try == "" { - stage.Try = src.Try - } - if len(stage.BasicEnv) == 0 { stage.BasicEnv = src.BasicEnv.Copy() } @@ -301,8 +306,8 @@ func mergeTasks(task *Task, ref string, taskMap TaskMap, circular map[string]boo } circular[ref] = true - src := taskMap[ref] - if src == nil { + src, ok := taskMap[ref] + if !ok { return fmt.Errorf("unknown task ref %s", ref) } @@ -311,12 +316,24 @@ func mergeTasks(task *Task, ref string, taskMap TaskMap, circular map[string]boo task.Description = src.Description } + if task.Type == "" { + task.Type = src.Type + } + + if len(task.Export) == 0 { + task.Export = src.Export.Copy() + } + if task.Dir == "" { task.Dir = src.Dir } - if task.Try == "" { - task.Try = src.Try + if len(task.Try) == 0 { + task.Try = src.Try.Copy() + } + + if len(task.Group) == 0 { + task.Group = src.Group.Copy() } if len(task.BasicEnv) == 0 { @@ -343,6 +360,11 @@ func mergeTasks(task *Task, ref string, taskMap TaskMap, circular map[string]boo task.Params = src.Params.Copy() } + if task.OnFail == nil && src.OnFail != nil { + c := *src.OnFail + task.OnFail = &c + } + mergeDefinition(task.Definition, src.Definition) if src.Ref != "" { @@ -369,37 +391,19 @@ func (mc *missionControl) prepareStages(ctx context.Context, capComm *CapComm, s // check stage to see if it has a reference to another stage if stage.Ref != "" { - if err := mergeStageRef(stage, stageMap); err != nil { + if err := mergeStageRef(&stage, stageMap); err != nil { return nil, errors.Wrapf(err, "%s merge with ref %s", stage.Name, stage.Ref) } } // prepare the stage - ops, onFail, err := mc.prepareStage(ctx, capComm, stage) + op, err := mc.prepareStage(ctx, capComm, stage) if err != nil { return nil, errors.Wrapf(err, "%s prepare", stage.Name) } - var dir string - if stage.Dir != "" { - dir, err = capComm.ExpandString(ctx, "dir", stage.Dir) - if err != nil { - return nil, errors.Wrapf(err, "%s dir expand", stage.Name) - } - } - - if len(ops) > 0 { - try, err := capComm.ExpandBool(ctx, "try", stage.Try) - if err != nil { - return nil, errors.Wrapf(err, "%s try expand", stage.Name) - } - - operations = append(operations, &operation{ - description: fmt.Sprintf("stage: %s", stage.Name), - makeItSo: engage(ctx, ops, dir), - try: try, - onFail: onFail, - }) + if op != nil { + operations = append(operations, op) } } @@ -436,46 +440,27 @@ func checkMustHaveParams(params Getter, must MustHaveParams) error { return loggee.BindMultiErrorFormatting(err) } -func (mc *missionControl) prepareFailStage(ctx context.Context, capComm *CapComm, stageMap StageMap, stage *Stage) (*operation, error) { +func (mc *missionControl) prepareFailStage(ctx context.Context, capComm *CapComm, stageMap StageMap, stage Stage) (*operation, error) { if stage.Name == "" { stage.Name = "onfail" } // check stage to see if it has a reference to another stage if stage.Ref != "" { - if err := mergeStageRef(stage, stageMap); err != nil { + if err := mergeStageRef(&stage, stageMap); err != nil { return nil, errors.Wrapf(err, "%s merge with ref %s", stage.Name, stage.Ref) } } // prepare the stage - ops, onFail, err := mc.prepareStage(ctx, capComm, stage) + op, err := mc.prepareStage(ctx, capComm, stage) if err != nil { return nil, errors.Wrapf(err, "%s prepare", stage.Name) } - - if len(ops) == 0 { - return nil, nil - } - - // handle any dir change - var dir string - if stage.Dir != "" { - dir, err = capComm.ExpandString(ctx, "dir", stage.Dir) - if err != nil { - return nil, errors.Wrapf(err, "%s dir expand", stage.Name) - } - } - - return &operation{ - description: fmt.Sprintf("stage: %s", stage.Name), - makeItSo: engage(ctx, ops, dir), - try: false, - onFail: onFail, - }, nil + return op, nil } -func createStageCapComm(ctx context.Context, missionCapComm *CapComm, stage *Stage) (*CapComm, error) { +func createStageCapComm(ctx context.Context, missionCapComm *CapComm, stage Stage) (*CapComm, error) { // Create a new CapComm for the stage capComm := missionCapComm.Copy(stage.NoTrust). MergeBasicEnvMap(stage.BasicEnv) @@ -494,29 +479,147 @@ func createStageCapComm(ctx context.Context, missionCapComm *CapComm, stage *Sta return capComm, nil } -func (mc *missionControl) prepareStage(ctx context.Context, missionCapComm *CapComm, stage *Stage) (operations, ExecuteFunc, error) { - var operations operations - +func (mc *missionControl) prepareStage(ctx context.Context, missionCapComm *CapComm, stage Stage) (*operation, error) { if stage.Filter.IsFiltered() { - return operations, nil, nil + return nil, nil } if err := checkMustHaveParams(missionCapComm.params, stage.Must); err != nil { - return nil, nil, err + return nil, err } // Create the cap comm for the stage capComm, err := createStageCapComm(ctx, missionCapComm, stage) if err != nil { - return nil, nil, err + return nil, err + } + + return mc.prepareTaskList(ctx, capComm, "stage: "+stage.Name, stage.Tasks, stage.OnFail, false, stage.Dir) +} + +func (mc *missionControl) prepareFailTask(ctx context.Context, capComm *CapComm, task Task) (*operation, error) { + if task.Name == "" { + task.Name = "onfail" + } + + // prepare the task + op, err := mc.prepareTask(ctx, capComm, task) + if err != nil { + return nil, errors.Wrapf(err, "prepare: %s", task.Name) + } + + return op, nil +} + +func taskCapComm(ctx context.Context, parentCapComm *CapComm, task Task) (*CapComm, error) { + // Create a new CapComm for the task + capComm := parentCapComm.Copy(task.NoTrust). + MergeBasicEnvMap(task.BasicEnv) + + // Merge the parameters + if err := capComm.MergeParams(ctx, task.Params); err != nil { + return nil, errors.Wrap(err, "merging params") + } + + // Merge and expand template envs + if err := capComm.MergeTemplateEnvs(ctx, task.Env); err != nil { + return nil, errors.Wrap(err, "merging template envs") + } + + return capComm, nil +} + +func (mc *missionControl) prepareTask(ctx context.Context, parentCapComm *CapComm, task Task) (*operation, error) { + if task.Filter.IsFiltered() { + return nil, nil + } + + if err := checkMustHaveParams(parentCapComm.params, task.Must); err != nil { + return nil, err + } + + capComm, err := taskCapComm(ctx, parentCapComm, task) + if err != nil { + return nil, err + } + + // determin task kind + taskKind, err := getTaskKind(task) + if err != nil { + return nil, err + } + + var op *operation + + switch taskKind { + case taskKindType: + return mc.prepareTaskKindType(ctx, capComm, task) + case taskKindTry: + op, err = mc.prepareTaskList(ctx, capComm, "try: "+task.Name, task.Try, task.OnFail, true, task.Dir) + case taskKindGroup: + op, err = mc.prepareTaskList(ctx, capComm, "group: "+task.Name, task.Group, task.OnFail, false, task.Dir) + } + + if err != nil { + return nil, err + } + + if op != nil && len(task.Export) > 0 { + // add in the exports + op.AddHandler(func(next ExecuteFunc) ExecuteFunc { + return func(opCtx context.Context) error { + err := next(opCtx) + if err == nil { + capComm.ExportVariables(task.Export) + } + return err + } + }) + } + + return op, nil +} + +func getTaskKind(task Task) (taskKind, error) { + kinds := 0 + + if task.Type != "" { + kinds++ + } + if len(task.Try) > 0 { + kinds++ + } + if len(task.Group) > 0 { + kinds++ } - // unlike stages tasks don't map unamed tasks - // stages needed to do this to support sequences but tasks don't. - taskMap := stage.Tasks.ToMap() + if kinds == 0 { + return taskKindNone, fmt.Errorf("task %s kind not specificed needs to be a type, group or try task", task.Name) + } + + if kinds > 1 { + return taskKindNone, fmt.Errorf("task %s has multiple kinds needs to be a single type, group or try task", task.Name) + } + if task.Type != "" { + return taskKindType, nil + } + if len(task.Try) > 0 { + return taskKindTry, nil + } + if len(task.Group) > 0 { + return taskKindGroup, nil + } + panic("kind?") +} + +func (mc *missionControl) prepareTaskList(ctx context.Context, capComm *CapComm, + groupDesc string, tasks Tasks, onFailTask *Task, + tryOp bool, taskDir string) (*operation, error) { + taskMap := tasks.ToMap() + var operations operations // Move onto tasks - for index, task := range stage.Tasks { + for index, task := range tasks { if task.Name == "" { task.Name = fmt.Sprintf("task[%d]", index) } @@ -524,14 +627,14 @@ func (mc *missionControl) prepareStage(ctx context.Context, missionCapComm *CapC // merge tasks if ref'd if task.Ref != "" { if err := mergeTaskRef(&task, taskMap); err != nil { - return nil, nil, errors.Wrapf(err, "%s merge with ref %s", task.Name, task.Ref) + return nil, errors.Wrapf(err, "%s merge with ref %s", task.Name, task.Ref) } } // prepare the task op, err := mc.prepareTask(ctx, capComm, task) if err != nil { - return nil, nil, errors.Wrapf(err, "prepare: %s", task.Name) + return nil, errors.Wrapf(err, "prepare: %s", task.Name) } if op != nil { @@ -541,55 +644,38 @@ func (mc *missionControl) prepareStage(ctx context.Context, missionCapComm *CapC // Is there ar failure task? var onFail ExecuteFunc - if stage.OnFail != nil { - onFailOp, err := mc.prepareFailTask(ctx, capComm, *stage.OnFail) + if onFailTask != nil { + onFailOp, err := mc.prepareFailTask(ctx, capComm, *onFailTask) if err != nil { - return nil, nil, err + return nil, err } onFail = onFailOp.makeItSo } - return operations, onFail, nil -} - -func (mc *missionControl) prepareFailTask(ctx context.Context, capComm *CapComm, task Task) (*operation, error) { - if task.Name == "" { - task.Name = "onfail" - } - - // prepare the task - op, err := mc.prepareTask(ctx, capComm, task) - if err != nil { - return nil, errors.Wrapf(err, "prepare: %s", task.Name) - } - - return op, nil -} - -func (mc *missionControl) prepareTask(ctx context.Context, stageCapComm *CapComm, task Task) (*operation, error) { - if err := checkMustHaveParams(stageCapComm.params, task.Must); err != nil { - return nil, err - } - - // Create a new CapComm for the task - capComm := stageCapComm.Copy(task.NoTrust). - MergeBasicEnvMap(task.BasicEnv) - - if task.Filter.IsFiltered() { + if len(operations) == 0 { return nil, nil } - // Merge the parameters - if err := capComm.MergeParams(ctx, task.Params); err != nil { - return nil, errors.Wrap(err, "merging params") + // handle any dir change + var dir string + var err error + if taskDir != "" { + dir, err = capComm.ExpandString(ctx, "dir", taskDir) + if err != nil { + return nil, errors.Wrapf(err, "%s dir expand", groupDesc) + } } - // Merge and expand template envs - if err := capComm.MergeTemplateEnvs(ctx, task.Env); err != nil { - return nil, errors.Wrap(err, "merging template envs") - } + return &operation{ + description: groupDesc, + makeItSo: engage(ctx, operations, dir), + try: tryOp, + onFail: onFail, + }, nil +} +func (mc *missionControl) prepareTaskKindType(ctx context.Context, capComm *CapComm, task Task) (*operation, error) { // Look up task tt, ok := mc.types[task.Type] if !ok { @@ -606,6 +692,17 @@ func (mc *missionControl) prepareTask(ctx context.Context, stageCapComm *CapComm return nil, nil } + // Is there ar failure task? + var onFail ExecuteFunc + if task.OnFail != nil { + onFailOp, err := mc.prepareFailTask(ctx, capComm, *task.OnFail) + if err != nil { + return nil, err + } + + onFail = onFailOp.makeItSo + } + var dir string if task.Dir != "" { dir, err = capComm.ExpandString(ctx, "dir", task.Dir) @@ -614,15 +711,11 @@ func (mc *missionControl) prepareTask(ctx context.Context, stageCapComm *CapComm } } - try, err := capComm.ExpandBool(ctx, "dir", task.Try) - if err != nil { - return nil, errors.Wrapf(err, "%s try expand", task.Name) - } - return &operation{ description: fmt.Sprintf("task: %s", task.Name), makeItSo: taskSwapDir(dir, taskFunc), - try: try, + try: false, + onFail: onFail, }, nil } @@ -705,13 +798,14 @@ func getStagesTooRun(mission *Mission, stageMap StageMap, flightSequences []stri return stagesToRun, nil } -func convertStagesToMap(stages Stages) (map[string]*Stage, error) { - m := make(map[string]*Stage) +func convertStagesToMap(stages Stages) (StageMap, error) { + m := make(StageMap) // prepare stages - for index, stage := range stages { + for _, stage := range stages { + // ignore un named stages if stage.Name == "" { - stage.Name = fmt.Sprintf("stage[%d]", index) + continue } if _, ok := m[stage.Name]; ok { @@ -813,3 +907,10 @@ func engage(_ context.Context, ops operations, dir string) ExecuteFunc { return nil } } + +// OperationHandler is a handler function that given a operations next function returns the function replacing it. +type OperationHandler func(next ExecuteFunc) ExecuteFunc + +func (op *operation) AddHandler(handler OperationHandler) { + op.makeItSo = handler(op.makeItSo) +} diff --git a/pkg/rocket/missioncontrol_test.go b/pkg/rocket/missioncontrol_test.go index 8c877da..335bb44 100644 --- a/pkg/rocket/missioncontrol_test.go +++ b/pkg/rocket/missioncontrol_test.go @@ -18,6 +18,7 @@ package rocket import ( "context" + "fmt" "os" "path/filepath" "testing" @@ -66,7 +67,7 @@ func (tt *testTaskType) Prepare(ctx context.Context, capComm *CapComm, task Task return func(ctx context.Context) error { tt.runCount++ - + fmt.Println("run:", task.Name) if tt.ch != nil { close(tt.ch) @@ -257,6 +258,37 @@ func TestLaunchMissionSeven(t *testing.T) { } } +func TestLaunchMissionTwelve(t *testing.T) { + loggee.SetLogger(stdlog.New()) + + mc := NewMissionControl() + tt := &testTaskType{t: t} + + mc.RegisterTaskTypes(tt) + + mission, missionLocation := loadMission("twelve") + + if err := mc.LaunchMission(context.Background(), missionLocation, mission); err != nil { + t.Error("Mission error for a ref group task", err) + } +} + +func TestLaunchMissionThirteen(t *testing.T) { + loggee.SetLogger(stdlog.New()) + + mc := NewMissionControl() + tt := &testTaskType{t: t} + + mc.RegisterTaskTypes(tt) + + // expect to break + mission, missionLocation := loadMission("thirteen") + + if err := mc.LaunchMission(context.Background(), missionLocation, mission); err == nil { + t.Error("Mission no error for a fail task") + } +} + func TestLaunchMissionWithSequencesNoneSpecified(t *testing.T) { loggee.SetLogger(stdlog.New()) diff --git a/pkg/rocket/testdata/seven.yml b/pkg/rocket/testdata/seven.yml index 645a507..b937f41 100644 --- a/pkg/rocket/testdata/seven.yml +++ b/pkg/rocket/testdata/seven.yml @@ -2,8 +2,8 @@ name: "seven" stages: - name: testing - try: true tasks: - - type: testTask - name: task to test - breakInRun: yes \ No newline at end of file + try: + - type: testTask + name: task to test + breakInRun: yes \ No newline at end of file diff --git a/pkg/rocket/testdata/thirteen.yml b/pkg/rocket/testdata/thirteen.yml new file mode 100644 index 0000000..4ff3980 --- /dev/null +++ b/pkg/rocket/testdata/thirteen.yml @@ -0,0 +1,13 @@ +name: "thirteen" + +stages: + - name: testing + tasks: + - type: testTask + name: task to test + breakInRun: yes + - type: testTask + name: clean up + onfail: + type: testTask + ref: clean up diff --git a/pkg/rocket/testdata/twelve.yml b/pkg/rocket/testdata/twelve.yml new file mode 100644 index 0000000..d9cfbde --- /dev/null +++ b/pkg/rocket/testdata/twelve.yml @@ -0,0 +1,14 @@ + +name: "twelve" + +stages: + - name: testing + tasks: + - name: peter + group: + - type: testTask + name: paul + - ref: paul + name: mary + - name: phil + ref: peter \ No newline at end of file