Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Feature finally and rescue for both step and task execution #15

Merged
merged 3 commits into from
Aug 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/up/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func main() {
if *ngoTaskName != "" {
u.Pln("-exec task:", *ngoTaskName)
if *instanceName != "" && *execprofile != "" {
u.InvalidAndExit("parameter validation", "instanceid (-i) and execprofile (-p) can not coexist, please only use one of them")
u.InvalidAndPanic("parameter validation", "instanceid (-i) and execprofile (-p) can not coexist, please only use one of them")
}
t := impl.NewTasker(*instanceName, *execprofile, initConfig)
impl.Pipein()
Expand Down
318 changes: 1 addition & 317 deletions biz/impl/blockfunc.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,9 @@
package impl

import (
"github.com/imdario/mergo"
ms "github.com/mitchellh/mapstructure"
"github.com/mohae/deepcopy"
"github.com/upcmd/up/biz"
"github.com/upcmd/up/model/core"
u "github.com/upcmd/up/utils"
ee "github.com/upcmd/up/utils/error"
"reflect"
"strconv"
)

type BlockFuncAction struct {
Expand All @@ -40,7 +34,7 @@ func (f *BlockFuncAction) Adapt() {
case []interface{}:
//detailed steps
err := ms.Decode(f.Do, &flow)
u.LogErrorAndExit("load steps", err, "steps has configuration problem, please fix it")
u.LogErrorAndPanic("load steps", err, "steps has configuration problem, please fix it")

default:
u.LogWarn("Block func", "Not implemented or void for no action!")
Expand All @@ -64,313 +58,3 @@ func BlockFlowRun(flow *Steps, execVars *core.Cache) {
flow.Exec(true)
BlockStack().Pop()
}

func (flow *Steps) ExecFlow() {

for idx, step := range *flow {

taskLayerCnt := TaskerRuntime().Tasker.TaskStack.GetLen()
u.LogDesc("block step", idx+1, taskLayerCnt, step.Name, step.Desc)
u.Ppmsgvvvv(step)

execStep := func() {
rtContext := StepRuntimeContext{
Stepname: step.Name,
Timeout: step.Timeout,
}
StepStack().Push(&rtContext)

//TODO: ??
step.ExecTest()

result := StepRuntime().Result
taskname := TaskerRuntime().Tasker.TaskStack.GetTop().(*TaskRuntimeContext).Taskname

//TODO: add support for block
if u.Contains([]string{FUNC_SHELL, FUNC_CALL}, step.Func) {
if step.Reg == "auto" {
TaskRuntime().ExecbaseVars.Put(u.Spf("register_%s_%s", taskname, step.Name), result.Output)
} else if step.Reg != "" {
TaskRuntime().ExecbaseVars.Put(u.Spf("%s", step.Reg), result.Output)
} else {
if step.Func == FUNC_SHELL {
TaskRuntime().ExecbaseVars.Put("last_result", result)
}
}
}

func() {
result := StepRuntime().Result

if result != nil && result.Code == 0 {
u.LogOk(".")
}

if !u.Contains(step.Flags, "ignoreError") {
if result != nil && result.Code != 0 {
u.InvalidAndExit("Failed And Not Ignored!", "You may want to continue and ignore the error")
}
}

}()

StepStack().Pop()
}

if !TaskerRuntime().Tasker.TaskBreak {
execStep()
} else {
TaskerRuntime().Tasker.TaskBreak = false
break
}

}

}

func (step *Step) ExecTest() {
var action biz.Do

var bizErr *ee.Error = ee.New()
var stepExecVars *core.Cache
stepExecVars = step.getRuntimeExecVarsTest("get plain exec vars")
//u.Ptmpdebug("99", stepExecVars)
validation(stepExecVars)

if step.Flags != nil && u.Contains(step.Flags, "pause") {
pause(stepExecVars)
}

routeFuncType := func(loopItem *LoopItem) {
if loopItem != nil {
stepExecVars.Put("loopitem", loopItem.Item)
stepExecVars.Put("loopindex", loopItem.Index)
stepExecVars.Put("loopindex1", loopItem.Index1)
}

switch step.Func {
case FUNC_SHELL:
funcAction := ShellFuncAction{
Do: step.Do,
Vars: stepExecVars,
}
action = biz.Do(&funcAction)

case FUNC_CALL:
funcAction := CallFuncAction{
Do: step.Do,
Vars: stepExecVars,
}
action = biz.Do(&funcAction)

case FUNC_BLOCK:
funcAction := BlockFuncAction{
Do: step.Do,
Vars: stepExecVars,
}
action = biz.Do(&funcAction)

case FUNC_CMD:
funcAction := CmdFuncAction{
Do: step.Do,
Vars: stepExecVars,
}
action = biz.Do(&funcAction)

case "":
u.InvalidAndExit("Step dispatch", "func name is empty and not defined")
bizErr.Mark = "func name not implemented"

default:
u.InvalidAndExit("Step dispatch", u.Spf("func name(%s) is not recognised and implemented", step.Func))
bizErr.Mark = "func name not implemented"
}
}

dryRunOrContinue := func() {
//example to stop further steps
//f := u.MustConditionToContinueFunc(func() bool {
// return action != nil
//})
//
//u.DryRunOrExit("Step Exec", f, "func name must be valid")

alloweErrors := []string{
"func name not implemented",
}

DryRunAndSkip(
bizErr.Mark,
alloweErrors,
ContinueFunc(
func() {
if step.Loop != nil {
rawUtil := step.Until
func() {
//loop points to a var name which is a slice
if reflect.TypeOf(step.Loop).Kind() == reflect.String {
loopVarName := Render(step.Loop.(string), stepExecVars)
loopObj := stepExecVars.Get(loopVarName)
if loopObj == nil {
u.InvalidAndExit("Evaluating loop var and object", u.Spf("Please use a correct varname:(%s) containing a list of values", loopVarName))
}
if reflect.TypeOf(loopObj).Kind() == reflect.Slice {
switch loopObj.(type) {
case []interface{}:
for idx, item := range loopObj.([]interface{}) {
routeFuncType(&LoopItem{idx, idx + 1, item})
if rawUtil != "" {
untilEval := Render(rawUtil, stepExecVars)
toBreak, err := strconv.ParseBool(untilEval)
u.LogErrorAndExit("evaluate until condition", err, u.Spf("please fix until condition evaluation: [%s]", untilEval))
if toBreak {
u.Pvvvv("loop util conditional break")
break
} else {
chainAction(&action)
}
} else {
chainAction(&action)
}
}

case []string:
for idx, item := range loopObj.([]string) {
routeFuncType(&LoopItem{idx, idx + 1, item})
if rawUtil != "" {
untilEval := Render(rawUtil, stepExecVars)
toBreak, err := strconv.ParseBool(untilEval)
u.LogErrorAndExit("evaluate until condition", err, u.Spf("please fix until condition evaluation: [%s]", untilEval))
if toBreak {
u.Pvvvv("loop util conditional break")
break
} else {
chainAction(&action)
}
} else {
chainAction(&action)
}
}

case []int64:
for idx, item := range loopObj.([]int64) {
routeFuncType(&LoopItem{idx, idx + 1, item})
if rawUtil != "" {
untilEval := Render(rawUtil, stepExecVars)
toBreak, err := strconv.ParseBool(untilEval)
u.LogErrorAndExit("evaluate until condition", err, u.Spf("please fix until condition evaluation: [%s]", untilEval))
if toBreak {
u.Pvvvv("loop util conditional break")
break
} else {
chainAction(&action)
}
} else {
chainAction(&action)
}
}

default:
u.LogWarn("loop item evaluation", "Loop item type is not supported yet!")
}
} else {
u.InvalidAndExit("evaluate loop var", "loop var is not a array/list/slice")
}
} else if reflect.TypeOf(step.Loop).Kind() == reflect.Slice {
//loop itself is a slice
for idx, item := range step.Loop.([]interface{}) {
routeFuncType(&LoopItem{idx, idx + 1, item})
if rawUtil != "" {
untilEval := Render(rawUtil, stepExecVars)
toBreak, err := strconv.ParseBool(untilEval)
u.LogErrorAndExit("evaluate until condition", err, u.Spf("please fix until condition evaluation: [%s]", untilEval))
if toBreak {
u.Pvvvv("loop util conditional break")
break
} else {
chainAction(&action)
}
} else {
chainAction(&action)
}
}
} else {
u.InvalidAndExit("evaluate loop items", "please either use a list or a template evaluation which could result in a value of a list")
}
}()

} else {
routeFuncType(nil)
chainAction(&action)
}

}),
nil,
)
}

func() {
if step.If != "" {
IfEval := Render(step.If, stepExecVars)
if IfEval != "<no value>" {
goahead, err := strconv.ParseBool(IfEval)
u.LogErrorAndExit("evaluate condition", err, u.Spf("please fix if condition evaluation: [%s]", IfEval))
if goahead {
dryRunOrContinue()
} else {
if step.Else != nil && step.Else != "" {
doElse(step.Else, stepExecVars)
} else {
u.Pvvv("condition failed, skip executing step", step.Name)
}
}
} else {
u.Pvvv("condition failed, skip executing step", step.Name)
}
} else {
dryRunOrContinue()
}

}()
}

func (step *Step) getRuntimeExecVarsTest(mark string) *core.Cache {
var execvars core.Cache
var resultVars *core.Cache

execvars = deepcopy.Copy(*TaskRuntime().ExecbaseVars).(core.Cache)

taskVars := TaskRuntime().TaskVars
mergo.Merge(&execvars, taskVars, mergo.WithOverride)
//u.Ptmpdebug("33", execvars)
//u.Ptmpdebug("44", step.Vars)
//if IsCalled() {
// u.Ptmpdebug("if", "if")
// if step.Vars != nil {
// mergo.Merge(&step.Vars, &execvars, mergo.WithOverride)
// resultVars = &step.Vars
// } else {
// resultVars = &execvars
// }
//} else {
// u.Ptmpdebug("else", "else")
// mergo.Merge(&execvars, &step.Vars, mergo.WithOverride)
// resultVars = &execvars
//}
blockvars := BlockStack().GetTop().(*BlockRuntimeContext).BlockBaseVars
mergo.Merge(&execvars, blockvars, mergo.WithOverride)
mergo.Merge(&execvars, &step.Vars, mergo.WithOverride)
resultVars = &execvars

u.Pfvvvv("current exec runtime[%s] vars:", mark)
u.Ppmsgvvvv(resultVars)
//u.Ptmpdebug("55", resultVars)

//so far the execvars includes: scope vars + scope dvars + global runtime vars + task vars
resultVars = VarsMergedWithDvars("local", resultVars, &step.Dvars, resultVars)

//so far the resultVars includes: the local vars + dvars rendered using execvars
u.Ppmsgvvvhint("overall final exec vars:", resultVars)
//u.Ptmpdebug("99", resultVars)
return resultVars
}
2 changes: 1 addition & 1 deletion biz/impl/callfunc.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func (f *CallFuncAction) Adapt() {

case []interface{}:
err := ms.Decode(f.Do, &tasknames)
u.LogErrorAndExit("call func adapter", err, "please ref to a task name only")
u.LogErrorAndPanic("call func adapter", err, "please ref to a task name only")

default:
u.LogWarn("call func", "Not implemented or void for no action!")
Expand Down
Loading