Skip to content

Commit 9177741

Browse files
committed
add tests when prestart/poststart/poststop hooks fail
Signed-off-by: Liang Chenye <[email protected]>
1 parent ed3bcb2 commit 9177741

File tree

9 files changed

+241
-19
lines changed

9 files changed

+241
-19
lines changed

validation/pidfile.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ func main() {
2424
defer os.RemoveAll(tempDir)
2525
tempPidFile := filepath.Join(tempDir, "pidfile")
2626

27+
g := util.GetDefaultGenerator()
28+
g.SetProcessArgs([]string{"true"})
2729
config := util.LifecycleConfig{
30+
Config: g,
2831
Actions: util.LifecycleActionCreate | util.LifecycleActionDelete,
2932
PreCreate: func(r *util.Runtime) error {
3033
r.SetID(uuid.NewV4().String())
@@ -51,9 +54,7 @@ func main() {
5154
},
5255
}
5356

54-
g := util.GetDefaultGenerator()
55-
g.SetProcessArgs([]string{"true"})
56-
err = util.RuntimeLifecycleValidate(g, config)
57+
err = util.RuntimeLifecycleValidate(config)
5758
t.Ok(err == nil, "create with '--pid-file' option works")
5859
if err != nil {
5960
diagnostic := map[string]string{

validation/poststart.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func main() {
2828
g := util.GetDefaultGenerator()
2929
output = filepath.Join(r.BundleDir, g.Spec().Root.Path, "output")
3030
poststart := rspec.Hook{
31-
Path: fmt.Sprintf("%s/%s/bin/sh", r.BundleDir, g.Spec().Root.Path),
31+
Path: filepath.Join(r.BundleDir, g.Spec().Root.Path, "/bin/sh"),
3232
Args: []string{
3333
"sh", "-c", fmt.Sprintf("echo 'post-start called' >> %s", output),
3434
},
@@ -73,7 +73,7 @@ func main() {
7373
},
7474
}
7575

76-
err := util.RuntimeLifecycleValidate(nil, config)
76+
err := util.RuntimeLifecycleValidate(config)
7777
if err != nil {
7878
diagnostic := map[string]string{
7979
"error": err.Error(),

validation/poststart_fail.go

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"os"
7+
"path/filepath"
8+
"time"
9+
10+
tap "github.com/mndrix/tap-go"
11+
rspec "github.com/opencontainers/runtime-spec/specs-go"
12+
"github.com/opencontainers/runtime-tools/specerror"
13+
"github.com/opencontainers/runtime-tools/validation/util"
14+
uuid "github.com/satori/go.uuid"
15+
)
16+
17+
func main() {
18+
t := tap.New()
19+
t.Header(0)
20+
21+
bundleDir, err := util.PrepareBundle()
22+
if err != nil {
23+
return
24+
}
25+
defer os.RemoveAll(bundleDir)
26+
27+
g := util.GetDefaultGenerator()
28+
output := filepath.Join(bundleDir, g.Spec().Root.Path, "output")
29+
poststart := rspec.Hook{
30+
Path: filepath.Join(bundleDir, g.Spec().Root.Path, "/bin/false"),
31+
Args: []string{"false"},
32+
}
33+
g.AddPostStartHook(poststart)
34+
poststartOK := rspec.Hook{
35+
Path: filepath.Join(bundleDir, g.Spec().Root.Path, "/bin/sh"),
36+
Args: []string{
37+
"sh", "-c", fmt.Sprintf("echo 'post-start called' >> %s", output),
38+
},
39+
}
40+
g.AddPostStartHook(poststartOK)
41+
g.SetProcessArgs([]string{"true"})
42+
config := util.LifecycleConfig{
43+
Config: g,
44+
BundleDir: bundleDir,
45+
Actions: util.LifecycleActionCreate | util.LifecycleActionStart | util.LifecycleActionDelete,
46+
PreCreate: func(r *util.Runtime) error {
47+
r.SetID(uuid.NewV4().String())
48+
return nil
49+
},
50+
PreDelete: func(r *util.Runtime) error {
51+
util.WaitingForStatus(*r, util.LifecycleStatusStopped, time.Second*10, time.Second)
52+
return nil
53+
},
54+
}
55+
56+
runErr := util.RuntimeLifecycleValidate(config)
57+
outputData, _ := ioutil.ReadFile(output)
58+
59+
// if runErr is not nil, it means the runtime generates an error
60+
// if outputData is not equal to the expected content, it means there is something wrong with the remaining hooks and lifecycle
61+
if runErr != nil || string(outputData) != "post-start called\n" {
62+
err := specerror.NewError(specerror.PoststartHookFailGenWarn, fmt.Errorf("if any poststart hook fails, the runtime MUST log a warning, but the remaining hooks and lifecycle continue as if the hook had succeeded"), rspec.Version)
63+
diagnostic := map[string]string{
64+
"error": err.Error(),
65+
}
66+
t.YAML(diagnostic)
67+
}
68+
69+
t.AutoPlan()
70+
}

validation/poststop.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func main() {
2929
g := util.GetDefaultGenerator()
3030
output = filepath.Join(r.BundleDir, g.Spec().Root.Path, "output")
3131
poststop := rspec.Hook{
32-
Path: fmt.Sprintf("%s/%s/bin/sh", r.BundleDir, g.Spec().Root.Path),
32+
Path: filepath.Join(r.BundleDir, g.Spec().Root.Path, "/bin/sh"),
3333
Args: []string{
3434
"sh", "-c", fmt.Sprintf("echo 'post-stop called' >> %s", output),
3535
},
@@ -90,7 +90,7 @@ func main() {
9090
},
9191
}
9292

93-
err := util.RuntimeLifecycleValidate(nil, config)
93+
err := util.RuntimeLifecycleValidate(config)
9494
if err != nil {
9595
diagnostic := map[string]string{
9696
"error": err.Error(),

validation/poststop_fail.go

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"os"
7+
"path/filepath"
8+
"time"
9+
10+
tap "github.com/mndrix/tap-go"
11+
rspec "github.com/opencontainers/runtime-spec/specs-go"
12+
"github.com/opencontainers/runtime-tools/specerror"
13+
"github.com/opencontainers/runtime-tools/validation/util"
14+
uuid "github.com/satori/go.uuid"
15+
)
16+
17+
func main() {
18+
t := tap.New()
19+
t.Header(0)
20+
21+
bundleDir, err := util.PrepareBundle()
22+
if err != nil {
23+
return
24+
}
25+
defer os.RemoveAll(bundleDir)
26+
27+
g := util.GetDefaultGenerator()
28+
output := filepath.Join(bundleDir, g.Spec().Root.Path, "output")
29+
poststop := rspec.Hook{
30+
Path: filepath.Join(bundleDir, g.Spec().Root.Path, "/bin/false"),
31+
Args: []string{"false"},
32+
}
33+
g.AddPostStopHook(poststop)
34+
poststopOK := rspec.Hook{
35+
Path: filepath.Join(bundleDir, g.Spec().Root.Path, "/bin/sh"),
36+
Args: []string{
37+
"sh", "-c", fmt.Sprintf("echo 'post-stop called' >> %s", output),
38+
},
39+
}
40+
g.AddPostStopHook(poststopOK)
41+
g.SetProcessArgs([]string{"true"})
42+
43+
config := util.LifecycleConfig{
44+
Config: g,
45+
BundleDir: bundleDir,
46+
Actions: util.LifecycleActionCreate | util.LifecycleActionStart | util.LifecycleActionDelete,
47+
PreCreate: func(r *util.Runtime) error {
48+
r.SetID(uuid.NewV4().String())
49+
return nil
50+
},
51+
PreDelete: func(r *util.Runtime) error {
52+
util.WaitingForStatus(*r, util.LifecycleStatusStopped, time.Second*10, time.Second)
53+
return nil
54+
},
55+
}
56+
57+
runErr := util.RuntimeLifecycleValidate(config)
58+
outputData, _ := ioutil.ReadFile(output)
59+
// if runErr is not nil, it means the runtime generates an error
60+
// if outputData is not equal to the expected content, it means there is something wrong with the remaining hooks and lifecycle
61+
if runErr != nil || string(outputData) != "post-stop called\n" {
62+
err := specerror.NewError(specerror.PoststopHookFailGenWarn, fmt.Errorf("if any poststop hook fails, the runtime MUST log a warning, but the remaining hooks and lifecycle continue as if the hook had succeeded"), rspec.Version)
63+
diagnostic := map[string]string{
64+
"error": err.Error(),
65+
}
66+
t.YAML(diagnostic)
67+
}
68+
69+
t.AutoPlan()
70+
}

validation/prestart.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func main() {
2727
g := util.GetDefaultGenerator()
2828
output = filepath.Join(r.BundleDir, g.Spec().Root.Path, "output")
2929
prestart := rspec.Hook{
30-
Path: fmt.Sprintf("%s/%s/bin/sh", r.BundleDir, g.Spec().Root.Path),
30+
Path: filepath.Join(r.BundleDir, g.Spec().Root.Path, "/bin/sh"),
3131
Args: []string{
3232
"sh", "-c", fmt.Sprintf("echo 'pre-start called' >> %s", output),
3333
},
@@ -72,7 +72,7 @@ func main() {
7272
},
7373
}
7474

75-
err := util.RuntimeLifecycleValidate(nil, config)
75+
err := util.RuntimeLifecycleValidate(config)
7676
if err != nil {
7777
diagnostic := map[string]string{
7878
"error": err.Error(),

validation/prestart_fail.go

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
8+
tap "github.com/mndrix/tap-go"
9+
rspec "github.com/opencontainers/runtime-spec/specs-go"
10+
"github.com/opencontainers/runtime-tools/specerror"
11+
"github.com/opencontainers/runtime-tools/validation/util"
12+
uuid "github.com/satori/go.uuid"
13+
)
14+
15+
func main() {
16+
t := tap.New()
17+
t.Header(0)
18+
19+
bundleDir, err := util.PrepareBundle()
20+
if err != nil {
21+
return
22+
}
23+
defer os.RemoveAll(bundleDir)
24+
25+
g := util.GetDefaultGenerator()
26+
prestart := rspec.Hook{
27+
Path: filepath.Join(bundleDir, g.Spec().Root.Path, "/bin/false"),
28+
Args: []string{"false"},
29+
}
30+
g.AddPreStartHook(prestart)
31+
g.SetProcessArgs([]string{"sh", "-c", fmt.Sprintf("touch %s", "/output")})
32+
containerID := uuid.NewV4().String()
33+
34+
config := util.LifecycleConfig{
35+
Config: g,
36+
BundleDir: bundleDir,
37+
Actions: util.LifecycleActionCreate | util.LifecycleActionStart,
38+
PreCreate: func(r *util.Runtime) error {
39+
r.SetID(containerID)
40+
return nil
41+
},
42+
}
43+
44+
runErr := util.RuntimeLifecycleValidate(config)
45+
_, outputErr := os.Stat(filepath.Join(bundleDir, g.Spec().Root.Path, "output"))
46+
47+
// query the state
48+
r, _ := util.NewRuntime(util.RuntimeCommand, "")
49+
r.SetID(containerID)
50+
_, stateErr := r.State()
51+
if stateErr != nil {
52+
// In case a container is created, delete it
53+
r.Delete()
54+
}
55+
56+
// if runErr is nil, it means the runtime does not generate an error
57+
// if outputErr is nil, it means the runtime calls the Process anyway
58+
// if stateErr is nil, it means it does not continue lifecycle at step 9
59+
if runErr == nil || outputErr == nil || stateErr == nil {
60+
err := specerror.NewError(specerror.PrestartHookFailGenError, fmt.Errorf("if any prestart hook fails, the runtime MUST generate an error, stop the container, and continue the lifecycle at step 9"), rspec.Version)
61+
diagnostic := map[string]string{
62+
"error": err.Error(),
63+
}
64+
t.YAML(diagnostic)
65+
}
66+
67+
t.AutoPlan()
68+
}

validation/state.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ func main() {
3232

3333
for _, c := range cases {
3434
config := util.LifecycleConfig{
35+
Config: g,
3536
Actions: c.action,
3637
PreCreate: func(r *util.Runtime) error {
3738
r.SetID(c.id)
@@ -42,7 +43,7 @@ func main() {
4243
return err
4344
},
4445
}
45-
err := util.RuntimeLifecycleValidate(g, config)
46+
err := util.RuntimeLifecycleValidate(config)
4647
t.Ok((err == nil) == c.errExpected, c.err.(*specerror.Error).Err.Err.Error())
4748
diagnostic := map[string]string{
4849
"reference": c.err.(*specerror.Error).Err.Reference,

validation/util/test.go

+21-9
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,13 @@ var lifecycleStatusMap = map[string]LifecycleStatus{
5858
}
5959

6060
// LifecycleConfig includes
61-
// 1. Actions to define the default running lifecycles.
62-
// 2. Four phases for user to add his/her own operations.
61+
// 1. Config to set the 'config.json'
62+
// 2. BundleDir to set the bundle directory
63+
// 3. Actions to define the default running lifecycles
64+
// 4. Four phases for user to add his/her own operations
6365
type LifecycleConfig struct {
66+
Config *generate.Generator
67+
BundleDir string
6468
Actions LifecycleAction
6569
PreCreate func(runtime *Runtime) error
6670
PostCreate func(runtime *Runtime) error
@@ -258,19 +262,27 @@ func RuntimeOutsideValidate(g *generate.Generator, f AfterFunc) error {
258262
}
259263

260264
// RuntimeLifecycleValidate validates runtime lifecycle.
261-
func RuntimeLifecycleValidate(g *generate.Generator, config LifecycleConfig) error {
262-
bundleDir, err := PrepareBundle()
263-
if err != nil {
264-
return err
265+
func RuntimeLifecycleValidate(config LifecycleConfig) error {
266+
var bundleDir string
267+
var err error
268+
269+
if config.BundleDir == "" {
270+
bundleDir, err = PrepareBundle()
271+
if err != nil {
272+
return err
273+
}
274+
defer os.RemoveAll(bundleDir)
275+
} else {
276+
bundleDir = config.BundleDir
265277
}
266-
defer os.RemoveAll(bundleDir)
278+
267279
r, err := NewRuntime(RuntimeCommand, bundleDir)
268280
if err != nil {
269281
return err
270282
}
271283

272-
if g != nil {
273-
if err := r.SetConfig(g); err != nil {
284+
if config.Config != nil {
285+
if err := r.SetConfig(config.Config); err != nil {
274286
return err
275287
}
276288
}

0 commit comments

Comments
 (0)