github.com/opencontainers/runtime-tools@v0.9.0/validation/hooks/hooks.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os/exec" 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 var output string 22 config := util.LifecycleConfig{ 23 Actions: util.LifecycleActionCreate | util.LifecycleActionStart | util.LifecycleActionDelete, 24 PreCreate: func(r *util.Runtime) error { 25 r.SetID(uuid.NewV4().String()) 26 g, err := util.GetDefaultGenerator() 27 if err != nil { 28 util.Fatal(err) 29 } 30 output = filepath.Join(r.BundleDir, g.Spec().Root.Path, "output") 31 shPath := filepath.Join(r.BundleDir, g.Spec().Root.Path, "/bin/sh") 32 err = g.AddPreStartHook(rspec.Hook{ 33 Path: shPath, 34 Args: []string{ 35 "sh", "-c", fmt.Sprintf("echo 'pre-start1 called' >> %s", output), 36 }, 37 }) 38 if err != nil { 39 return err 40 } 41 err = g.AddPreStartHook(rspec.Hook{ 42 Path: shPath, 43 Args: []string{ 44 "sh", "-c", fmt.Sprintf("echo 'pre-start2 called' >> %s", output), 45 }, 46 }) 47 if err != nil { 48 return err 49 } 50 err = g.AddPostStartHook(rspec.Hook{ 51 Path: shPath, 52 Args: []string{ 53 "sh", "-c", fmt.Sprintf("echo 'post-start1 called' >> %s", output), 54 }, 55 }) 56 if err != nil { 57 return err 58 } 59 err = g.AddPostStartHook(rspec.Hook{ 60 Path: shPath, 61 Args: []string{ 62 "sh", "-c", fmt.Sprintf("echo 'post-start2 called' >> %s", output), 63 }, 64 }) 65 if err != nil { 66 return err 67 } 68 err = g.AddPostStopHook(rspec.Hook{ 69 Path: shPath, 70 Args: []string{ 71 "sh", "-c", fmt.Sprintf("echo 'post-stop1 called' >> %s", output), 72 }, 73 }) 74 if err != nil { 75 return err 76 } 77 err = g.AddPostStopHook(rspec.Hook{ 78 Path: shPath, 79 Args: []string{ 80 "sh", "-c", fmt.Sprintf("echo 'post-stop2 called' >> %s", output), 81 }, 82 }) 83 if err != nil { 84 return err 85 } 86 g.SetProcessArgs([]string{"true"}) 87 return r.SetConfig(g) 88 }, 89 PreDelete: func(r *util.Runtime) error { 90 util.WaitingForStatus(*r, util.LifecycleStatusStopped, time.Second*10, time.Second) 91 return nil 92 }, 93 } 94 95 err := util.RuntimeLifecycleValidate(config) 96 outputData, _ := ioutil.ReadFile(output) 97 if err == nil && string(outputData) != "pre-start1 called\npre-start2 called\npost-start1\npost-start2\npost-stop1\npost-stop2\n" { 98 err = specerror.NewError(specerror.PosixHooksCalledInOrder, fmt.Errorf("Hooks MUST be called in the listed order"), rspec.Version) 99 diagnostic := map[string]string{ 100 "error": err.Error(), 101 } 102 t.YAML(diagnostic) 103 } else { 104 diagnostic := map[string]string{ 105 "error": err.Error(), 106 } 107 if e, ok := err.(*exec.ExitError); ok { 108 if len(e.Stderr) > 0 { 109 diagnostic["stderr"] = string(e.Stderr) 110 } 111 } 112 t.YAML(diagnostic) 113 } 114 115 t.AutoPlan() 116 }