add lifecycle validation#558
Conversation
Before 'start', we have 'create' operation, so I think this spec means:
How about make a testcase like this:
so when 'create', the $bundle/$rootfs/output should be empty, |
|
I think |
2f516d4 to
7c18974
Compare
|
According to the description of lifecycle, I have determined the order of calls for each part: create -> start -> prestart -> process -> poststart -> delete -> poststop The code is updated according to this call order. |
validation/lifecycle.go
Outdated
| return err | ||
| } | ||
| if string(outputData) != "" { | ||
| return errors.New("Wrong call") |
There was a problem hiding this comment.
I am not quite sure what to say about this type of error. Any suggestions?
There was a problem hiding this comment.
I am not quite sure what to say about this type of error.
The associated specerror entries start around here.
There was a problem hiding this comment.
Depending on what is read, the specific error is different. It would be very troublesome to be accurate to every error condition. So instead of making a further distinction, I want to output the error directly.
Do you think it is necessary to distinguish between each error?
There was a problem hiding this comment.
Yes, each error should explicitly reflect the relevant 'specerror'.
validation/lifecycle.go
Outdated
| t.Header(0) | ||
|
|
||
| prestart := rspec.Hook{ | ||
| Path: "/usr/bin/prestart", |
There was a problem hiding this comment.
Where does /usr/bin/prestart come from?
There was a problem hiding this comment.
About this path, I thought it was created automatically when added.
Maybe this idea is wrong.
Do you have any suggestions for the path?
There was a problem hiding this comment.
Do you have any suggestions for the
path?
The echo on our BusyBox tarball?
There was a problem hiding this comment.
I'm writing a demo to show my idea, I'll link to you soom.
|
Following your idea, I made some changes: https://github.com/liangchenye/ocitools/blob/gotest/validation/lifecycle.go
About the 'Wrong Error", I suggest we may split the lifecycle.go to 'prestart.go', 'poststart.go' and the etc. Each hook has multiply spec errors, it will make it easier to maintain and cover all the errors. How do you think ? @q384566678 |
|
On Wed, Jan 31, 2018 at 07:39:28PM -0800, 梁辰晔 (Liang Chenye) wrote:
1. using 'sh' and 'echo' in the bundle
This general approach looks good to me, but you'll want to use Go's
filepath.Join to compose the paths for Windows compat. And we'll need
future work to ensure we have a usable tarball for the host platform
that includes ‘sh’, ‘echo’, and anything else we need.
About the 'Wrong Error", I suggest we may split the lifecycle.go to
'prestart.go', 'poststart.go' and the etc. Each hook has multiply
spec errors, it will make it easier to maintain and cover all the
errors.
This sounds like a good idea to me. Common code can always go into a
helper, although I'm not sure how much overlap there will be.
|
|
@liangchenye That sounds good. I'll update patch in this way. Thank you for your advice. |
1c6387c to
4ad25ac
Compare
|
updated, @liangchenye @wking PTAL. |
validation/poststart.go
Outdated
| }, | ||
| PostCreate: func(r *util.Runtime) error { | ||
| outputData, err := ioutil.ReadFile(output) | ||
| if err != nil { |
There was a problem hiding this comment.
It is expected to get an 'err', since the 'output' will not exist.
validation/poststart.go
Outdated
| return err | ||
| } | ||
| switch string(outputData) { | ||
| case "": |
There was a problem hiding this comment.
It should not happen, we can move it to 'default' part.
validation/poststart.go
Outdated
| switch string(outputData) { | ||
| case "": | ||
| return nil | ||
| case "post-start called\n": |
There was a problem hiding this comment.
We can make it simpler:
if strings.Contains(string(outputData), "post-start") {
return specerror.NewError(specerror.PoststartTimin
} else if strings.Contains(string(outputData), "process") {
return specerror.NewError(specerror.ProcNotRunAtResRequest)
}
validation/poststart.go
Outdated
| PreDelete: func(r *util.Runtime) error { | ||
| outputData, err := ioutil.ReadFile(output) | ||
| if err != nil { | ||
| return err |
There was a problem hiding this comment.
Also
return fmt.Errorf("%v\n%v", specerror.NewError(specerror.PoststartHooksInvoke,
|
I commented in prestart.go and it misses one case: |
validation/poststop.go
Outdated
| }, | ||
| PostCreate: func(r *util.Runtime) error { | ||
| outputData, err := ioutil.ReadFile(output) | ||
| if err != nil { |
There was a problem hiding this comment.
Similar to 'poststart.go', we should get an error: the output file is not exist.
validation/prestart.go
Outdated
| }, | ||
| PostCreate: func(r *util.Runtime) error { | ||
| outputData, err := ioutil.ReadFile(output) | ||
| if err != nil { |
validation/prestart.go
Outdated
| return err | ||
| } | ||
| switch string(outputData) { | ||
| case "": |
validation/poststop.go
Outdated
| return err | ||
| } | ||
| switch string(outputData) { | ||
| case "": |
validation/poststart.go
Outdated
| return err | ||
| } | ||
| switch string(outputData) { | ||
| case "": |
validation/prestart.go
Outdated
| return err | ||
| } | ||
| switch string(outputData) { | ||
| case "": |
validation/prestart.go
Outdated
| return specerror.NewError(specerror.PrestartTiming, fmt.Errorf("Pre-start hooks MUST be called after the `start` operation is called"), rspec.Version) | ||
| case "process called\n": | ||
| return specerror.NewError(specerror.ProcNotRunAtResRequest, fmt.Errorf("The user-specified program (from process) MUST NOT be run at this time"), rspec.Version) | ||
| case "pre-start called\nprocess called\n", "process called\npre-start called\n": |
There was a problem hiding this comment.
remove this, change
case "pre-start called\n"
to
strings.Contain
validation/poststop.go
Outdated
| return err | ||
| } | ||
| switch string(outputData) { | ||
| case "": |
|
Same to other hooks. |
92b6907 to
70a423b
Compare
3c3b7d6 to
8dca66d
Compare
|
@liangchenye @wking updated, PTAL. |
1c2ac39 to
32fe314
Compare
|
|
|
I saw another problem in the test code, the process 'output' filepath is wrong, it is already running inside the container. |
validation/poststart.go
Outdated
| } | ||
|
|
||
| g.AddPostStartHook(poststart) | ||
| g.SetProcessArgs([]string{"sh", "-c", fmt.Sprintf("echo 'process called' >> %s", output)}) |
There was a problem hiding this comment.
Change to:
g.SetProcessArgs([]string{"sh", "-c", fmt.Sprintf("echo 'process called' >> %s", "/output")})
| } | ||
| return nil | ||
| }, | ||
| PreDelete: func(r *util.Runtime) error { |
There was a problem hiding this comment.
I suggest we can add
util.WaitingForStatus(*r, util.LifecycleStatusStopped, time.Second * 10, time.Second)
'start' will return immediately, although 'echo' runs fast, but we are not sure how many time it costs. (for example, in runc/cc/Kata project)
| PostCreate: func(r *util.Runtime) error { | ||
| outputData, err := ioutil.ReadFile(output) | ||
| if err == nil { | ||
| if strings.Contains(string(outputData), "post-start called") { |
validation/prestart.go
Outdated
| } | ||
|
|
||
| g.AddPreStartHook(prestart) | ||
| g.SetProcessArgs([]string{"sh", "-c", fmt.Sprintf("echo 'process called' >> %s", output)}) |
| return nil | ||
| }, | ||
| PreDelete: func(r *util.Runtime) error { | ||
| outputData, err := ioutil.ReadFile(output) |
There was a problem hiding this comment.
Same, I suggest to add 'Wait.."
| PostCreate: func(r *util.Runtime) error { | ||
| outputData, err := ioutil.ReadFile(output) | ||
| if err == nil { | ||
| if strings.Contains(string(outputData), "pre-start called") { |
There was a problem hiding this comment.
I always get this in 'runc'.
| case "process called\n": | ||
| fmt.Fprintln(os.Stderr, "WARNING: The poststart hook invoke fails") | ||
| return nil | ||
| case "post-start called\nprocess called\n": |
There was a problem hiding this comment.
since 'post-start' runs in 'create', the sequence here is wrong.
validation/poststop.go
Outdated
| } | ||
|
|
||
| g.AddPostStopHook(poststop) | ||
| g.SetProcessArgs([]string{"sh", "-c", fmt.Sprintf("echo 'process called' >> %s", output)}) |
|
Report an issue in 'runc' project: opencontainers/runc#1710. |
Signed-off-by: Zhou Hao <zhouhao@cn.fujitsu.com>
32fe314 to
09ddc02
Compare
I am going to add a validation of the lifecycle, the specific norms are as follows:
But I can not confirm the specific call state, so for the moment I'm just verifying that the relevant command has not been called.
This is just a preliminary idea. Lifecycle validation also need more work, any comments welcome. Or you can write a new patch.
Signed-off-by: Zhou Hao zhouhao@cn.fujitsu.com