github.com/mgoltzsche/ctnr@v0.7.1-alpha/run/types.go (about) 1 package run 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "os/exec" 8 "syscall" 9 10 "github.com/opencontainers/runtime-spec/specs-go" 11 "github.com/pkg/errors" 12 ) 13 14 type ContainerBundle interface { 15 ID() string 16 Dir() string 17 Spec() (*specs.Spec, error) 18 Close() error 19 } 20 21 type ContainerConfig struct { 22 Id string 23 Bundle ContainerBundle 24 Io ContainerIO 25 NoPivotRoot bool 26 NoNewKeyring bool 27 DestroyOnClose bool 28 } 29 30 type ContainerIO struct { 31 Stdin io.Reader 32 Stdout io.Writer 33 Stderr io.Writer 34 } 35 36 func NewStdContainerIO() ContainerIO { 37 return ContainerIO{ 38 Stdout: os.Stdout, 39 Stderr: os.Stderr, 40 } 41 } 42 43 type ContainerManager interface { 44 NewContainer(cfg *ContainerConfig) (Container, error) 45 Get(id string) (Container, error) 46 List() ([]ContainerInfo, error) 47 Kill(id string, signal os.Signal, all bool) error 48 Exist(id string) (bool, error) 49 } 50 51 type Container interface { 52 ID() string 53 Rootfs() string 54 Start() error 55 // TODO: expose process 56 Exec(*specs.Process, ContainerIO) (Process, error) 57 Destroy() error 58 Process 59 } 60 61 type Process interface { 62 Wait() error 63 Stop() 64 Close() error 65 } 66 67 type ContainerInfo struct { 68 ID string 69 Status string 70 } 71 72 type ExitError struct { 73 containerId string 74 code int 75 cause error 76 } 77 78 func (e *ExitError) Code() int { 79 return e.code 80 } 81 82 func (e *ExitError) ContainerID() string { 83 return e.containerId 84 } 85 86 func (e *ExitError) Error() string { 87 return e.cause.Error() 88 } 89 90 func (e *ExitError) Format(s fmt.State, verb rune) { 91 type formatter interface { 92 Format(s fmt.State, verb rune) 93 } 94 e.cause.(formatter).Format(s, verb) 95 } 96 97 func NewExitError(err error, containerId string) error { 98 if err == nil { 99 return nil 100 } 101 if exiterr, ok := err.(*exec.ExitError); ok { 102 if status, ok := exiterr.Sys().(syscall.WaitStatus); ok { 103 code := status.ExitStatus() 104 return &ExitError{containerId, code, errors.New(fmt.Sprintf("%s terminated: exit code %d", containerId, code))} 105 } 106 } 107 return errors.New(err.Error()) 108 } 109 110 func FindExitError(err error) *ExitError { 111 if err != nil { 112 type causer interface { 113 Cause() error 114 } 115 if e, ok := err.(*ExitError); ok { 116 return e 117 } 118 if e, ok := err.(causer); ok && e.Cause() != nil { 119 return FindExitError(e.Cause()) 120 } 121 } 122 return nil 123 }