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  }