-
Notifications
You must be signed in to change notification settings - Fork 160
Fix #556 #557
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
Fix #556 #557
Conversation
ae63341 to
56857d8
Compare
56857d8 to
b483dc1
Compare
|
This PR does two things:
It is similar to So if this approach is useful, we can merge 'RuntimeInsideValidate', ‘RuntimeOutsideValidate' and 'RuntimeLifecycleValidate' into one.
|
b483dc1 to
78f41b5
Compare
validation/pidfile.go
Outdated
| t.Header(0) | ||
|
|
||
| var lifecycle util.LifecycleFuncs | ||
| tempFile, err := ioutil.TempFile("", "oci-pidfile") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This approach (using an empty but already existing PID file) seems strange to me. We may want to update the CLI spec to specifically address this case and keep this test, but I think a more traditional test would be to use a temp directory with a --pid-file path that is a direct child of that temp directory (so the target path does not exist when create is called).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not an existing PID file, it is also a new temp file, similar to using TempDir + 'pid'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not an existing PID file, it is also a new temp file, similar to using TempDir + 'pid'.
The TempFile docs say it creates the file. TempDir + "pid" would not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it.
validation/pidfile.go
Outdated
| util.Fatal(err) | ||
| } | ||
| tempPidFile := tempFile.Name() | ||
| lifecycle.Setup = func(r *util.Runtime) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of initializing lifecycle and then filling in these properties, it might be more idiomatic to use:
lifecycle := util.LifecycleFuncs{
Setup: func(…) error {
…
},
PreStart: …,
PostStart: …,
}
validation/pidfile.go
Outdated
| defer os.Remove(tempPidFile) | ||
|
|
||
| lifecycle.PreStart = func(r *util.Runtime) error { | ||
| pidData, err := ioutil.ReadFile(tempPidFile) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want a PostCreate slot (maybe instead of the PreStart slot?). We can run the --pid-file test with create / kill / delete without involving start.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1, 'PostCreat'e is better, 'Prestart' might also be confusing,
validation/pidfile.go
Outdated
| } | ||
|
|
||
| lifecycle.PostStart = func(r *util.Runtime) error { | ||
| time.Sleep(1 * time.Second) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's this about?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Waiting for the container to stop, or we cannot delete it.
There should be a better function to waiting for the status change.
validation/pidfile.go
Outdated
| return nil | ||
| } | ||
|
|
||
| lifecycle.PostStop = nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this the default already? I don't think we need this line.
validation/pidfile.go
Outdated
| lifecycle.PostStop = nil | ||
|
|
||
| g := util.GetDefaultGenerator() | ||
| g.SetProcessArgs([]string{"ls"}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather use:
g.Spec().Process = niland skip start.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'runc' has a bug: if the 'Process' is nil, runc crashes.
Besides this, 'runc' does not follow the CLI spec, it applies the 'process args' when create a container.
I add a test to change the 'process args' in PostCreate, in theory, runc should execute the new args, but it does not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'runc' has a bug: if the 'Process' is nil, runc crashes
create crashes? That would be a bug.
I add a test to change the 'process args' in PostCreate, in theory, runc should execute the new args, but it does not.
No, the runtime must ignore any post-create config changes, so runc is fine on that point.
validation/util/container.go
Outdated
| } | ||
|
|
||
| // SetPidFile sets the pid file | ||
| func (r *Runtime) SetPidFile(pidFile string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PidFile is already public. I don't think we need a setter.
|
|
||
| // Delete a container | ||
| func (r *Runtime) Delete() error { | ||
| func (r *Runtime) Delete() ([]byte, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we returning stderr? You don't seem to consume this new value anywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use this to debug why 'Delete' fails.
The 'time.Sleep' line is coming from this.
validation/util/test.go
Outdated
| } | ||
| } | ||
|
|
||
| stderr, err = r.Start() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we'll want a flag to toggle whether we call Start or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So something like this
func RuntimeLifecycleValidate(g *generate.Generator, lifecycle *LifecycleFuncs, actions LifecycleAction) {
...
if actions & LifeCycleCreate {
stderr, err := r.Create()
}
...
if actions & LifeCycleStart {
stderr, err = r.Start()
}
...
}
78f41b5 to
9df90d8
Compare
Two issues were found, but I think they could be solved in other PRs.
PTAL @wking @q384566678 @Mashimiao |
9df90d8 to
08d0bd1
Compare
| util.Fatal(err) | ||
| } | ||
| tempPidFile := filepath.Join(tempDir, "pidfile") | ||
| defer os.RemoveAll(tempDir) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I'd rather swap the order of these two lines to get the cleanup defer right after the TempDir error check. filepath.Join cannot error, but having the defer set as early as possible would give me warm fuzzy feelings ;).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I'll update it.
| ) | ||
|
|
||
| var lifecycleStatusMap = map[string]LifecycleStatus{ | ||
| "creating": LifecycleStatusCreating, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or these could just be strings:
type LivecycleStatus string
const (
LifecycleStatusCreating = "creating"
…
)and then you cast with LifecycleStatus(state.Status). I don't see a need for indirection through an integer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An 'integer' is useful when we expect to have multiple statuses. For example, if we want to delete a container, we expected to have 'created' or 'stopped' status. So we can 'WaitingForStatus(Created|Stopped)'.
validation/util/test.go
Outdated
| } | ||
|
|
||
| // RuntimeLifecycleValidate validates runtime lifecycle. | ||
| func RuntimeLifecycleValidate(g *generate.Generator, lifecycle *LifecycleFuncs, actions LifecycleAction) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a need to split funcs from actions. Can we rename LifecycleFuncs to LifecycleConfig (or just Lifecycle?) and add an Actions property?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for this
validation/util/test.go
Outdated
| } | ||
| } | ||
|
|
||
| if lifecycle != nil && lifecycle.PostStop != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think anything running after Delete should be PostDelete. This PR currently seems to handle stop and delete in one step (or maybe it is never intended to call stop and instead waits for the container to stop on its own?), but calling this setting PostDelete makes sense regardless of an explicit stop or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So all the embedded functions should have different new, I'll update it too.
I prefer calling the 'stop' in the related test cases, for example, if we want to test 'kill'.
We can add test codes in the 'PreDelete'. (PreDelete is better than PreStop)
08d0bd1 to
a7f123b
Compare
Fixes opencontainers#556 Signed-off-by: Liang Chenye <liangchenye@huawei.com>
a7f123b to
5e8b51e
Compare
|
Updated by using lifecycleConfig (merge funcs and actions), now the funcs are symmetrical: PreCreate/PostCreate, PreDelete/PostDelete |
1 similar comment
| return nil | ||
| }, | ||
| PreDelete: func(r *util.Runtime) error { | ||
| return util.WaitingForStatus(*r, util.LifecycleStatusCreated, time.Second*10, time.Second*1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't need this, because a container must be created before create returns. Maybe a runc bug?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
runc does not implement 'creating' lifecycle ,
it is always 'created' or 'fails'.
From the spec, it should be like this:
- user run
runX create x - user run
runX status x
it should be 'creating' (assuming the creating takes a long time).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
runcdoes not implement 'creating' lifecycle...
That's definitely a bug. And there's also some CLI spec wording about create's exit timing. I think we can drop this, and I'll file a runc patch.
The runtime-spec defines a 'creating' status [1] and requires the 'create' operation to finish creating the container [2,3]. Our command line API also requires the 'create' command to block until creation completes: Callers MAY block on this command's successful exit to trigger post-create activity. runc does not support 'creating' yet [4], and it seems to return from 'create' before having quite finished (or we wouldn't have needed the code I'm removing in this commit). However, both of those are runc problems. These tests are about validating spec compliance, not about working around runc's issues, so remove the crutches. [1]: https://github.com/opencontainers/runtime-spec/blame/v1.0.1/runtime.md#L19 [2]: https://github.com/opencontainers/runtime-spec/blame/v1.0.1/runtime.md#L54 [3]: https://github.com/opencontainers/runtime-spec/blame/v1.0.1/runtime.md#L101 [4]: opencontainers#557 (comment) Signed-off-by: W. Trevor King <wking@tremily.us>
The runtime-spec defines a 'creating' status [1] and requires the 'create' operation to finish creating the container [2,3]. Our command line API also requires the 'create' command to block until creation completes: Callers MAY block on this command's successful exit to trigger post-create activity. runc does not support 'creating' yet [4], and it seems to return from 'create' before having quite finished (or we wouldn't have needed the code I'm removing in this commit). However, both of those are runc problems. These tests are about validating spec compliance, not about working around runc's issues, so remove the crutches. [1]: https://github.com/opencontainers/runtime-spec/blame/v1.0.1/runtime.md#L19 [2]: https://github.com/opencontainers/runtime-spec/blame/v1.0.1/runtime.md#L54 [3]: https://github.com/opencontainers/runtime-spec/blame/v1.0.1/runtime.md#L101 [4]: opencontainers#557 (comment) Signed-off-by: W. Trevor King <wking@tremily.us>
The runtime-spec defines a 'creating' status [1] and requires the 'create' operation to finish creating the container [2,3]. Our command line API also requires the 'create' command to block until creation completes: Callers MAY block on this command's successful exit to trigger post-create activity. runc does not support 'creating' yet [4], and it seems to return from 'create' before having quite finished (or we wouldn't have needed the code I'm removing in this commit). However, both of those are runc problems. These tests are about validating spec compliance, not about working around runc's issues, so remove the crutches. [1]: https://github.com/opencontainers/runtime-spec/blame/v1.0.1/runtime.md#L19 [2]: https://github.com/opencontainers/runtime-spec/blame/v1.0.1/runtime.md#L54 [3]: https://github.com/opencontainers/runtime-spec/blame/v1.0.1/runtime.md#L101 [4]: opencontainers#557 (comment) Signed-off-by: W. Trevor King <wking@tremily.us>
Signed-off-by: Liang Chenye liangchenye@huawei.com