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 hooks stdin test #589

Merged
merged 1 commit into from
Mar 19, 2018
Merged

add hooks stdin test #589

merged 1 commit into from
Mar 19, 2018

Conversation

liangchenye
Copy link
Member

Signed-off-by: Liang Chenye liangchenye@huawei.com

@liangchenye
Copy link
Member Author

It is a WIP PR to test the container state that passed to hooks over 'stdin':

The state of the container MUST be passed to hooks over stdin so that they may do work appropriate to the current state of the container.

I try to use timeout 1 cat > output to collect stdin content and compare the output file to do the test.
One problem is, it is not possible for the 'poststop' hook to get the container state since the container would be deleted before 'poststop hook' been called.

Poststop
The post-stop hooks MUST be called after the container is deleted but before the delete operation returns. Cleanup or debugging functions are examples of such a hook.

@alban
Copy link
Contributor

alban commented Mar 5, 2018

One problem is, it is not possible for the 'poststop' hook to get the container state since the container would be deleted before 'poststop hook' been called.

It's not possible to call funC state container-id and compare with the output in the hook but we could still check that the state has the correct id, bundle and annotations.

I had a look at runc but it always gives an empty "status" (opencontainers/runc#1057 & opencontainers/runc#1741) and as you pointed out, it does not call the hooks at the correct time (opencontainers/runc#1710).

Since the spec does not have a "status=deleted", I wonder what's the correct status to send on stdin in the poststop hook. Does the spec explain that?

@liangchenye
Copy link
Member Author

No, if it is deleted, there won't be a 'status=delete' since:

Once a container is deleted its ID MAY be used by a subsequent container

I think we can not send a status on stdin in the poststop hook.

@liangchenye liangchenye changed the title WIP: add hooks stdin test add hooks stdin test Mar 15, 2018
@liangchenye
Copy link
Member Author

In the updated version, I check the 'ID', 'Bundle' and 'Annotations' of the container state in 'prestart', 'poststart' and 'poststop' hooks. The 'PID','status' and 'ociVersion' is unpredictable.

The 'poststop' hook is also checked here according to current spec requirement.

@liangchenye
Copy link
Member Author

PTAL @q384566678 @wking @alban

@wking
Copy link
Contributor

wking commented Mar 15, 2018

I think we can not send a status on stdin in the poststop hook.

This is opencontainers/runtime-spec#958. We may end up with a deleted state, but as it stands I think runtimes have to use stopped there.

The 'PID','status' and 'ociVersion' is unpredictable.

Depending on how you read the spec, ociVersion needs to match either the config version or the state version. I have opencontainers/runtime-spec#903 in flight to settle on the latter. But until runtime-spec cuts a release with a different/expanded state schema, I think we can safely use:

if state.Version != "1.0.0" && state.Version != "1.0.1" {
    // complain
}

The container process can check its PID, and then this test can compare with the states it recieved.

@liangchenye
Copy link
Member Author

I'm working on the PID now.
About the spec version, my new update is just comparing the Version: rspecs.Version,

g.AddPreStartHook(rspecs.Hook{
Path: filepath.Join(bundleDir, g.Spec().Root.Path, "/bin/sh"),
Args: []string{
"sh", "-c", fmt.Sprintf("timeout -t 1 cat > %s", filepath.Join(outputDir, "prestart")),
Copy link
Contributor

@wking wking Mar 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is your timeout from? It's not in POSIX, and coreutils uses -k / --kill-after, not -t.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is in the busybox 1.28, in the new rootfs-amd64.tar.gz.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is in the busybox 1.28, in the new rootfs-amd64.tar.gz.

The lack of standardization is unfortunate, because hooks are called from the runtime namespace, so the version in the container doesn't matter. We could work around that with {bundle-path}/rootfs/bin/timeout here, but it's probably better to set Timeout in the hook structure and skip the timeout command.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, the timeout in hooks is much more rational.

if err != nil {
return err
}
containerPid = state.Pid
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be more reliable if we dropped the state call and collected this from the container process itself (where you currently just use true).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

echo $$ will output the id inside the container. It is different with the state one - It is 'seen' by host.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

echo $$ will output the id inside the container. It is different with the state one - It is 'seen' by host.

Ah right, you'd need the PID namespace too to translate, and that would break down for VM-based runtimes anyway. So I'm on board with your current state call.

@liangchenye
Copy link
Member Author

I'll revoke my version test. It is wrong.

@liangchenye
Copy link
Member Author

liangchenye commented Mar 15, 2018

Updated.
The 'version' test is dropped. I don't find a good definition of an expected version in the runtime spec.
We can get a 'Version' from r.State just like what we do to PID. But I don't see the meaning of doing this.

PTAL @q384566678

}
for _, file := range []string{"prestart", "poststart", "poststop"} {
err := stdinStateCheck(outputDir, file, expectedState)
util.SpecErrorOK(t, err == nil, specerror.NewError(specerror.PosixHooksStateToStdin, fmt.Errorf("the state of the container MUST be passed to %q hook over stdin so that they may do work appropriate to the current state of the container", file), rspecs.Version), err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can probably drop "so that they...of the container" from the error message. That motivation is in the spec for folks who care, but you don't need it for the check.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated.

}

if !reflect.DeepEqual(state.Annotations, expectedState.Annotations) {
return fmt.Errorf("wrong annotations \"%v\" in the stdin of %s hook, expected \"%v\"", state.Annotations, hookName, state.Annotations)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last parameter should be expectedState.Annotations.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated.

Signed-off-by: Liang Chenye <liangchenye@huawei.com>
@zhouhao3
Copy link

zhouhao3 commented Mar 16, 2018

The following error occurred while I was testing:

TAP version 13
not ok 1 - the state of the container MUST be passed to "prestart" hook over stdin
  ---
  {
    "error": "wrong annotations \"map[]\" in the stdin of prestart hook, expected \"map[org.opencontainers.runtime-tools:hook stdin test]\"",
    "reference": "https://github.com/opencontainers/runtime-spec/blob/v1.0.0/config.md#posix-platform-hooks"
  }
  ...
not ok 2 - the state of the container MUST be passed to "poststart" hook over stdin
  ---
  {
    "error": "wrong annotations \"map[]\" in the stdin of poststart hook, expected \"map[org.opencontainers.runtime-tools:hook stdin test]\"",
    "reference": "https://github.com/opencontainers/runtime-spec/blob/v1.0.0/config.md#posix-platform-hooks"
  }
  ...
not ok 3 - the state of the container MUST be passed to "poststop" hook over stdin
  ---
  {
    "error": "wrong annotations \"map[]\" in the stdin of poststop hook, expected \"map[org.opencontainers.runtime-tools:hook stdin test]\"",
    "reference": "https://github.com/opencontainers/runtime-spec/blob/v1.0.0/config.md#posix-platform-hooks"
  }
  ...
1..3

@liangchenye
Copy link
Member Author

@q384566678 which 'runc' version do you use? Annotations are supported in mine.

runc --version
...
commit: e9cdc3906f18...
...

@zhouhao3
Copy link

runc --version
runc version 1.0.0-rc4+dev
commit: 91e979501348cb4cb13b5fb4437cc5d9ecd94b5d
spec: 1.0.0

@zhouhao3
Copy link

It's ok when I update the runc.

@zhouhao3
Copy link

zhouhao3 commented Mar 16, 2018

LGTM

Approved with PullApprove

@wking
Copy link
Contributor

wking commented Mar 16, 2018

It's ok when I update the runc.

We should really check status to notice runc failing becaue of opencontainers/runc#1710 and opencontainers/runc#1741.

@zhouhao3 zhouhao3 merged commit b3796e2 into opencontainers:master Mar 19, 2018
@liangchenye
Copy link
Member Author

liangchenye commented Mar 19, 2018

My understanding of the related spec is:
prestart hook status SHOULD be 'created'.
poststart hook status SHOULD be 'running'.
poststop hook status SHOULD not be 'creating/created/running/stopped', a 'nil' status or a runtime defined status would be OK.

I'll add a new PR to check this.

##Prestart

The pre-start hooks MUST be called after the start operation is called but before the user-specified program command is executed. ...

##Poststart

The post-start hooks MUST be called after the user-specified process is executed but before the start operation returns....

##Poststop

The post-stop hooks MUST be called after the container is deleted but before the delete operation returns....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants