Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions libcontainer/configs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/Sirupsen/logrus"
"github.com/opencontainers/runtime-spec/specs-go"
)

type Rlimit struct {
Expand Down Expand Up @@ -243,13 +244,7 @@ func (hooks Hooks) MarshalJSON() ([]byte, error) {
}

// HookState is the payload provided to a hook on execution.
type HookState struct {
Version string `json:"ociVersion"`
ID string `json:"id"`
Pid int `json:"pid"`
Root string `json:"root"`
BundlePath string `json:"bundlePath"`
}
type HookState specs.State

type Hook interface {
// Run executes the hook with the provided state.
Expand Down
24 changes: 12 additions & 12 deletions libcontainer/configs/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ func TestMarshalHooksWithUnexpectedType(t *testing.T) {

func TestFuncHookRun(t *testing.T) {
state := configs.HookState{
Version: "1",
ID: "1",
Pid: 1,
Root: "root",
Version: "1",
ID: "1",
Pid: 1,
BundlePath: "/bundle",
}

fHook := configs.NewFunctionHook(func(s configs.HookState) error {
Expand All @@ -138,10 +138,10 @@ func TestFuncHookRun(t *testing.T) {

func TestCommandHookRun(t *testing.T) {
state := configs.HookState{
Version: "1",
ID: "1",
Pid: 1,
Root: "root",
Version: "1",
ID: "1",
Pid: 1,
BundlePath: "/bundle",
}
timeout := time.Second

Expand All @@ -161,10 +161,10 @@ func TestCommandHookRun(t *testing.T) {

func TestCommandHookRunTimeout(t *testing.T) {
state := configs.HookState{
Version: "1",
ID: "1",
Pid: 1,
Root: "root",
Version: "1",
ID: "1",
Pid: 1,
BundlePath: "/bundle",
}
timeout := (10 * time.Millisecond)

Expand Down
9 changes: 4 additions & 5 deletions libcontainer/container_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,6 @@ func (c *linuxContainer) start(process *Process, isInit bool) error {
Version: c.config.Version,
ID: c.id,
Pid: parent.pid(),
Root: c.config.Rootfs,
BundlePath: utils.SearchLabels(c.config.Labels, "bundle"),
}
for i, hook := range c.config.Hooks.Poststart {
Expand Down Expand Up @@ -1038,10 +1037,10 @@ func (c *linuxContainer) criuNotifications(resp *criurpc.CriuResp, process *Proc
case notify.GetScript() == "setup-namespaces":
if c.config.Hooks != nil {
s := configs.HookState{
Version: c.config.Version,
ID: c.id,
Pid: int(notify.GetPid()),
Root: c.config.Rootfs,
Version: c.config.Version,
ID: c.id,
Pid: int(notify.GetPid()),
BundlePath: utils.SearchLabels(c.config.Labels, "bundle"),
}
for i, hook := range c.config.Hooks.Prestart {
if err := hook.Run(s); err != nil {
Expand Down
46 changes: 40 additions & 6 deletions libcontainer/integration/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package integration

import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"os"
Expand Down Expand Up @@ -1048,25 +1049,44 @@ func TestHook(t *testing.T) {
if testing.Short() {
return
}
root, err := newTestRoot()

bundle, err := newTestBundle()
ok(t, err)
defer os.RemoveAll(root)
defer remove(bundle)

rootfs, err := newRootfs()
ok(t, err)
defer remove(rootfs)

config := newTemplateConfig(rootfs)
expectedBundlePath := "/path/to/bundle/path"
expectedBundlePath := bundle
config.Labels = append(config.Labels, fmt.Sprintf("bundle=%s", expectedBundlePath))

getRootfsFromBundle := func(bundle string) (string, error) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why not declare this as a function in utils_test.go. Seems a bit odd to define it like this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Because this is a temporary function which is only used by TestHook, so I thought it's not worth a standalone function, and utils_test.go should contain common functions. :-)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Eh, okay. I don't really like it but it's just a test so w/e.

f, err := os.Open(filepath.Join(bundle, "config.json"))
if err != nil {
return "", err
}

var config configs.Config
if err = json.NewDecoder(f).Decode(&config); err != nil {
return "", err
}
return config.Rootfs, nil
}

config.Hooks = &configs.Hooks{
Prestart: []configs.Hook{
configs.NewFunctionHook(func(s configs.HookState) error {
if s.BundlePath != expectedBundlePath {
t.Fatalf("Expected prestart hook bundlePath '%s'; got '%s'", expectedBundlePath, s.BundlePath)
}

f, err := os.Create(filepath.Join(s.Root, "test"))
root, err := getRootfsFromBundle(s.BundlePath)
if err != nil {
return err
}
f, err := os.Create(filepath.Join(root, "test"))
if err != nil {
return err
}
Expand All @@ -1079,7 +1099,11 @@ func TestHook(t *testing.T) {
t.Fatalf("Expected poststart hook bundlePath '%s'; got '%s'", expectedBundlePath, s.BundlePath)
}

return ioutil.WriteFile(filepath.Join(s.Root, "test"), []byte("hello world"), 0755)
root, err := getRootfsFromBundle(s.BundlePath)
if err != nil {
return err
}
return ioutil.WriteFile(filepath.Join(root, "test"), []byte("hello world"), 0755)
}),
},
Poststop: []configs.Hook{
Expand All @@ -1088,10 +1112,20 @@ func TestHook(t *testing.T) {
t.Fatalf("Expected poststop hook bundlePath '%s'; got '%s'", expectedBundlePath, s.BundlePath)
}

return os.RemoveAll(filepath.Join(s.Root, "test"))
root, err := getRootfsFromBundle(s.BundlePath)
if err != nil {
return err
}
return os.RemoveAll(filepath.Join(root, "test"))
}),
},
}

// write config of json format into config.json under bundle
f, err := os.OpenFile(filepath.Join(bundle, "config.json"), os.O_CREATE|os.O_RDWR, 0644)
ok(t, err)
ok(t, json.NewEncoder(f).Encode(config))

container, err := factory.Create("test", config)
ok(t, err)

Expand Down
11 changes: 11 additions & 0 deletions libcontainer/integration/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@ func newTestRoot() (string, error) {
return dir, nil
}

func newTestBundle() (string, error) {
dir, err := ioutil.TempDir("", "bundle")
if err != nil {
return "", err
}
if err := os.MkdirAll(dir, 0700); err != nil {
return "", err
}
return dir, nil
}

// newRootfs creates a new tmp directory and copies the busybox root filesystem
func newRootfs() (string, error) {
dir, err := ioutil.TempDir("", "")
Expand Down
9 changes: 4 additions & 5 deletions libcontainer/process_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,10 +339,10 @@ func (p *initProcess) start() error {
if !p.config.Config.Namespaces.Contains(configs.NEWNS) {
if p.config.Config.Hooks != nil {
s := configs.HookState{
Version: p.container.config.Version,
ID: p.container.id,
Pid: p.pid(),
Root: p.config.Config.Rootfs,
Version: p.container.config.Version,
ID: p.container.id,
Pid: p.pid(),
BundlePath: utils.SearchLabels(p.config.Config.Labels, "bundle"),
}
for i, hook := range p.config.Config.Hooks.Prestart {
if err := hook.Run(s); err != nil {
Expand All @@ -362,7 +362,6 @@ func (p *initProcess) start() error {
Version: p.container.config.Version,
ID: p.container.id,
Pid: p.pid(),
Root: p.config.Config.Rootfs,
BundlePath: utils.SearchLabels(p.config.Config.Labels, "bundle"),
}
for i, hook := range p.config.Config.Hooks.Prestart {
Expand Down
1 change: 0 additions & 1 deletion libcontainer/state_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ func runPoststopHooks(c *linuxContainer) error {
s := configs.HookState{
Version: c.config.Version,
ID: c.id,
Root: c.config.Rootfs,
BundlePath: utils.SearchLabels(c.config.Labels, "bundle"),
}
for _, hook := range c.config.Hooks.Poststop {
Expand Down