finally/resuce support in subtask level
Showcases that you could make the workflow to pass through with cleanup, however you can still make the exit code as none zero to mark it fail
Demo
source
Main task yaml file
tasks:
- name: task
task:
- func: call
desc: |
expect sub_task to close file each time in loop iteration
loop:
- item1
- item2
- item3
do:
- sub_task
- name: sub_task
task:
- func: cmd
do:
- name: print
cmd: 'case {{.loopitem}}'
- func: shell
name: step1
desc: conditionall trigger the error
do:
- echo "case {{.loopitem}} "
- echo "hello"|grep "world"
if: '{{eq .loopitem "item2"}}'
- func: cmd
name: step2
desc: |
in this case, since there is no ignoreError, the exception was captured by task level finaly code block
opened file is safely closed
to make the flow to continue to reach step2, use ignoreError
do:
- name: print
cmd: step 2
desc: |
without rescue, the execution will return a non-zero return code in shell and also report the error
with rescue, the program will return 0
rescue: true
finally:
- func: shell
name: close_file
desc: |
ensure the opened file is closed
do:
- echo "close the file ....."
Main log file
loading [Config]: ./tests/functests/upconfig.yml
Main config:
Version -> 1.0.0
RefDir -> ./tests/functests
WorkDir -> cwd
AbsWorkDir -> /up_project/up
TaskFile -> f0188
Verbose -> vvv
ModuleName -> self
ShellType -> /bin/sh
MaxCallLayers -> 8
Timeout -> 3600000
MaxModuelCallLayers -> 256
EntryTask -> task
ModRepoUsernameRef ->
ModRepoPasswordRef ->
work dir: /up_project/up
-exec task: task
loading [Task]: ./tests/functests/f0188
module: [self], instance id: [dev], exec profile: []
profile - envVars:
(*core.Cache)({
})
Task1: [task ==> task: ]
-Step1: [
expect sub_task to close file each time in loop iteration
]
self: final context exec vars:
(*core.Cache)({
"up_runtime_task_layer_number": 0
})
=Task2: [task ==> sub_task: without rescue, the execution will return a non-zero return code in shell and also report the error
with rescue, the program will return 0
]
--Step1:
self: final context exec vars:
(*core.Cache)({
"loopindex1": 1,
"up_runtime_task_layer_number": 1,
"loopitem": "item1",
"loopindex": 0
})
~~SubStep1: [print: ]
case item1
--Step2: [step1: conditionall trigger the error ]
self: final context exec vars:
(*core.Cache)({
"loopindex1": 1,
"up_runtime_task_layer_number": 1,
"loopitem": "item1",
"loopindex": 0
})
condition failed, skip executing step step1
--Step3: [
step2in this case, since there is no ignoreError, the exception was captured by task level finaly code block
opened file is safely closed
to make the flow to continue to reach step2, use ignoreError
]
self: final context exec vars:
(*core.Cache)({
"loopitem": "item1",
"loopindex": 0,
"loopindex1": 1,
"last_result": (*utils.ExecResult)(<nil>),
"up_runtime_task_layer_number": 1
})
~~SubStep1: [print: ]
step 2
task Finally:
-Step1: [
close_fileensure the opened file is closed
]
self: final context exec vars:
(*core.Cache)({
"up_runtime_task_layer_number": 1,
"loopitem": "item1",
"loopindex": 0,
"loopindex1": 1
})
cmd( 1):
echo "close the file ....."
-
close the file .....
-
.. ok
. ok
=Task2: [task ==> sub_task: without rescue, the execution will return a non-zero return code in shell and also report the error
with rescue, the program will return 0
]
--Step1:
self: final context exec vars:
(*core.Cache)({
"loopitem": "item2",
"loopindex": 1,
"loopindex1": 2,
"last_result": (*utils.ExecResult)({
Cmd: "echo \"close the file .....\"",
Code: 0,
Output: "close the file .....",
ErrMsg: ""
}),
"up_runtime_task_layer_number": 1
})
~~SubStep1: [print: ]
case item2
--Step2: [step1: conditionall trigger the error ]
self: final context exec vars:
(*core.Cache)({
"up_runtime_task_layer_number": 1,
"loopitem": "item2",
"loopindex": 1,
"loopindex1": 2,
"last_result": (*utils.ExecResult)({
Cmd: "echo \"close the file .....\"",
Code: 0,
Output: "close the file .....",
ErrMsg: ""
})
})
cmd( 1):
echo "case {{.loopitem}} "
-
case item2
-
.. ok
cmd( 2):
echo "hello"|grep "world"
-
-
.. failed(suppressed if it is not the last step)
task Finally:
--Step1: [
close_fileensure the opened file is closed
]
self: final context exec vars:
(*core.Cache)({
"loopindex1": 2,
"up_runtime_task_layer_number": 1,
"loopitem": "item2",
"loopindex": 1
})
cmd( 1):
echo "close the file ....."
-
close the file .....
-
.. ok
. ok
WARN: [Rescued in task level, but not advised!] - [setting rescue to yes/true to continue is not recommended
it is advised to locate root cause of the problem, fix it and re-run the task again
it is the best practice to test the execution in your ci pipeline to eliminate problems rather than dynamically fix using rescue]
==Task2: [task/sub_task ==> sub_task: without rescue, the execution will return a non-zero return code in shell and also report the error
with rescue, the program will return 0
]
---Step1:
self: final context exec vars:
(*core.Cache)({
"loopindex1": 3,
"last_result": (*utils.ExecResult)({
Cmd: "echo \"close the file .....\"",
Code: 0,
Output: "close the file .....",
ErrMsg: ""
}),
"up_runtime_task_layer_number": 2,
"loopitem": "item3",
"loopindex": 2
})
~~~SubStep1: [print: ]
case item3
---Step2: [step1: conditionall trigger the error ]
self: final context exec vars:
(*core.Cache)({
"last_result": (*utils.ExecResult)({
Cmd: "echo \"close the file .....\"",
Code: 0,
Output: "close the file .....",
ErrMsg: ""
}),
"up_runtime_task_layer_number": 2,
"loopitem": "item3",
"loopindex": 2,
"loopindex1": 3
})
condition failed, skip executing step step1
---Step3: [
step2in this case, since there is no ignoreError, the exception was captured by task level finaly code block
opened file is safely closed
to make the flow to continue to reach step2, use ignoreError
]
self: final context exec vars:
(*core.Cache)({
"loopitem": "item3",
"loopindex": 2,
"loopindex1": 3,
"last_result": (*utils.ExecResult)(<nil>),
"up_runtime_task_layer_number": 2
})
~~~SubStep1: [print: ]
step 2
task Finally:
--Step1: [
close_fileensure the opened file is closed
]
self: final context exec vars:
(*core.Cache)({
"up_runtime_task_layer_number": 2,
"loopitem": "item3",
"loopindex": 2,
"loopindex1": 3
})
cmd( 1):
echo "close the file ....."
-
close the file .....
-
.. ok
. ok
WARN: [Not rescued in task level] - [please assess the panic problem and cause, fix it before re-run the task]
task finally -> ERROR: Failed And Not Ignored! [You may want to continue and ignore the error]
Logs with different verbose level
Raw logs with different verbose level
Other references: