mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-12 09:46:25 +08:00
2be806d139
Test that CommandHook actually executes a new process with the given env variables, parameters and json state. This commit also solves an issue with the previous approach that was calling 'os.Exit(0)' failing to signal test failures. Signed-off-by: Mauricio Vásquez <mauricio@kinvolk.io>
227 lines
5.6 KiB
Go
227 lines
5.6 KiB
Go
package configs_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/opencontainers/runc/libcontainer/configs"
|
|
"github.com/opencontainers/runtime-spec/specs-go"
|
|
)
|
|
|
|
func TestUnmarshalHooks(t *testing.T) {
|
|
timeout := time.Second
|
|
|
|
hookCmd := configs.NewCommandHook(configs.Command{
|
|
Path: "/var/vcap/hooks/hook",
|
|
Args: []string{"--pid=123"},
|
|
Env: []string{"FOO=BAR"},
|
|
Dir: "/var/vcap",
|
|
Timeout: &timeout,
|
|
})
|
|
|
|
hookJson, err := json.Marshal(hookCmd)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
for _, hookName := range configs.HookNameList {
|
|
hooks := configs.Hooks{}
|
|
err = hooks.UnmarshalJSON([]byte(fmt.Sprintf(`{"%s" :[%s]}`, hookName, hookJson)))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(hooks[hookName], configs.HookList{hookCmd}) {
|
|
t.Errorf("Expected %s to equal %+v but it was %+v", hookName, hookCmd, hooks[hookName])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestUnmarshalHooksWithInvalidData(t *testing.T) {
|
|
hook := configs.Hooks{}
|
|
err := hook.UnmarshalJSON([]byte(`{invalid-json}`))
|
|
if err == nil {
|
|
t.Error("Expected error to occur but it was nil")
|
|
}
|
|
}
|
|
|
|
func TestMarshalHooks(t *testing.T) {
|
|
timeout := time.Second
|
|
|
|
hookCmd := configs.NewCommandHook(configs.Command{
|
|
Path: "/var/vcap/hooks/hook",
|
|
Args: []string{"--pid=123"},
|
|
Env: []string{"FOO=BAR"},
|
|
Dir: "/var/vcap",
|
|
Timeout: &timeout,
|
|
})
|
|
|
|
hook := configs.Hooks{
|
|
configs.Prestart: configs.HookList{hookCmd},
|
|
configs.CreateRuntime: configs.HookList{hookCmd},
|
|
configs.CreateContainer: configs.HookList{hookCmd},
|
|
configs.StartContainer: configs.HookList{hookCmd},
|
|
configs.Poststart: configs.HookList{hookCmd},
|
|
configs.Poststop: configs.HookList{hookCmd},
|
|
}
|
|
hooks, err := hook.MarshalJSON()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Note Marshal seems to output fields in alphabetical order
|
|
hookCmdJson := `[{"path":"/var/vcap/hooks/hook","args":["--pid=123"],"env":["FOO=BAR"],"dir":"/var/vcap","timeout":1000000000}]`
|
|
h := fmt.Sprintf(`{"createContainer":%[1]s,"createRuntime":%[1]s,"poststart":%[1]s,"poststop":%[1]s,"prestart":%[1]s,"startContainer":%[1]s}`, hookCmdJson)
|
|
if string(hooks) != h {
|
|
t.Errorf("Expected hooks %s to equal %s", string(hooks), h)
|
|
}
|
|
}
|
|
|
|
func TestMarshalUnmarshalHooks(t *testing.T) {
|
|
timeout := time.Second
|
|
|
|
hookCmd := configs.NewCommandHook(configs.Command{
|
|
Path: "/var/vcap/hooks/hook",
|
|
Args: []string{"--pid=123"},
|
|
Env: []string{"FOO=BAR"},
|
|
Dir: "/var/vcap",
|
|
Timeout: &timeout,
|
|
})
|
|
|
|
hook := configs.Hooks{
|
|
configs.Prestart: configs.HookList{hookCmd},
|
|
configs.CreateRuntime: configs.HookList{hookCmd},
|
|
configs.CreateContainer: configs.HookList{hookCmd},
|
|
configs.StartContainer: configs.HookList{hookCmd},
|
|
configs.Poststart: configs.HookList{hookCmd},
|
|
configs.Poststop: configs.HookList{hookCmd},
|
|
}
|
|
hooks, err := hook.MarshalJSON()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
umMhook := configs.Hooks{}
|
|
err = umMhook.UnmarshalJSON(hooks)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !reflect.DeepEqual(umMhook, hook) {
|
|
t.Errorf("Expected hooks to be equal after mashaling -> unmarshaling them: %+v, %+v", umMhook, hook)
|
|
}
|
|
}
|
|
|
|
func TestMarshalHooksWithUnexpectedType(t *testing.T) {
|
|
fHook := configs.NewFunctionHook(func(*specs.State) error {
|
|
return nil
|
|
})
|
|
hook := configs.Hooks{
|
|
configs.CreateRuntime: configs.HookList{fHook},
|
|
}
|
|
hooks, err := hook.MarshalJSON()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
h := `{"createContainer":null,"createRuntime":null,"poststart":null,"poststop":null,"prestart":null,"startContainer":null}`
|
|
if string(hooks) != h {
|
|
t.Errorf("Expected hooks %s to equal %s", string(hooks), h)
|
|
}
|
|
}
|
|
|
|
func TestFuncHookRun(t *testing.T) {
|
|
state := &specs.State{
|
|
Version: "1",
|
|
ID: "1",
|
|
Status: "created",
|
|
Pid: 1,
|
|
Bundle: "/bundle",
|
|
}
|
|
|
|
fHook := configs.NewFunctionHook(func(s *specs.State) error {
|
|
if !reflect.DeepEqual(state, s) {
|
|
t.Errorf("Expected state %+v to equal %+v", state, s)
|
|
}
|
|
return nil
|
|
})
|
|
|
|
fHook.Run(state)
|
|
}
|
|
|
|
func TestCommandHookRun(t *testing.T) {
|
|
state := &specs.State{
|
|
Version: "1",
|
|
ID: "1",
|
|
Status: "created",
|
|
Pid: 1,
|
|
Bundle: "/bundle",
|
|
}
|
|
|
|
stateJson, err := json.Marshal(state)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
verifyCommandTemplate := `#!/bin/sh
|
|
if [ "$1" != "testarg" ]; then
|
|
echo "Bad value for $1. Expected 'testarg', found '$1'"
|
|
exit 1
|
|
fi
|
|
if [ -z "$FOO" ] || [ "$FOO" != BAR ]; then
|
|
echo "Bad value for FOO. Expected 'BAR', found '$FOO'"
|
|
exit 1
|
|
fi
|
|
expectedJson=%q
|
|
read JSON
|
|
if [ "$JSON" != "$expectedJson" ]; then
|
|
echo "Bad JSON received. Expected '$expectedJson', found '$JSON'"
|
|
exit 1
|
|
fi
|
|
exit 0
|
|
`
|
|
verifyCommand := fmt.Sprintf(verifyCommandTemplate, stateJson)
|
|
filename := "/tmp/runc-hooktest.sh"
|
|
os.Remove(filename)
|
|
if err := ioutil.WriteFile(filename, []byte(verifyCommand), 0700); err != nil {
|
|
t.Fatalf("Failed to create tmp file: %v", err)
|
|
}
|
|
defer os.Remove(filename)
|
|
|
|
cmdHook := configs.NewCommandHook(configs.Command{
|
|
Path: filename,
|
|
Args: []string{filename, "testarg"},
|
|
Env: []string{"FOO=BAR"},
|
|
Dir: "/",
|
|
})
|
|
|
|
if err := cmdHook.Run(state); err != nil {
|
|
t.Errorf(fmt.Sprintf("Expected error to not occur but it was %+v", err))
|
|
}
|
|
}
|
|
|
|
func TestCommandHookRunTimeout(t *testing.T) {
|
|
state := &specs.State{
|
|
Version: "1",
|
|
ID: "1",
|
|
Status: "created",
|
|
Pid: 1,
|
|
Bundle: "/bundle",
|
|
}
|
|
timeout := 100 * time.Millisecond
|
|
|
|
cmdHook := configs.NewCommandHook(configs.Command{
|
|
Path: "/bin/sleep",
|
|
Args: []string{"/bin/sleep", "1"},
|
|
Timeout: &timeout,
|
|
})
|
|
|
|
if err := cmdHook.Run(state); err == nil {
|
|
t.Error("Expected error to occur but it was nil")
|
|
}
|
|
}
|