github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/containerd/integration-test/container_utils_test.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "sort" 11 "syscall" 12 "time" 13 14 "github.com/docker/containerd/api/grpc/types" 15 "github.com/golang/protobuf/ptypes" 16 "github.com/golang/protobuf/ptypes/timestamp" 17 "golang.org/x/net/context" 18 "golang.org/x/sys/unix" 19 ) 20 21 func (cs *ContainerdSuite) GetLogs() string { 22 b, _ := ioutil.ReadFile(cs.logFile.Name()) 23 return string(b) 24 } 25 26 func (cs *ContainerdSuite) Events(from time.Time, storedOnly bool, id string) (types.API_EventsClient, error) { 27 var ( 28 ftsp *timestamp.Timestamp 29 err error 30 ) 31 if !from.IsZero() { 32 ftsp, err = ptypes.TimestampProto(from) 33 if err != nil { 34 return nil, err 35 } 36 } 37 38 return cs.grpcClient.Events(context.Background(), &types.EventsRequest{Timestamp: ftsp, StoredOnly: storedOnly, Id: id}) 39 } 40 41 func (cs *ContainerdSuite) ListRunningContainers() ([]*types.Container, error) { 42 resp, err := cs.grpcClient.State(context.Background(), &types.StateRequest{}) 43 if err != nil { 44 return nil, err 45 } 46 return resp.Containers, nil 47 } 48 49 func (cs *ContainerdSuite) SignalContainerProcess(id string, procID string, sig uint32) error { 50 _, err := cs.grpcClient.Signal(context.Background(), &types.SignalRequest{ 51 Id: id, 52 Pid: procID, 53 Signal: sig, 54 }) 55 return err 56 } 57 58 func (cs *ContainerdSuite) SignalContainer(id string, sig uint32) error { 59 return cs.SignalContainerProcess(id, "init", sig) 60 } 61 62 func (cs *ContainerdSuite) KillContainer(id string) error { 63 return cs.SignalContainerProcess(id, "init", uint32(syscall.SIGKILL)) 64 } 65 66 func (cs *ContainerdSuite) UpdateContainerResource(id string, rs *types.UpdateResource) error { 67 _, err := cs.grpcClient.UpdateContainer(context.Background(), &types.UpdateContainerRequest{ 68 Id: id, 69 Pid: "init", 70 Status: "", 71 Resources: rs, 72 }) 73 return err 74 } 75 76 func (cs *ContainerdSuite) PauseContainer(id string) error { 77 _, err := cs.grpcClient.UpdateContainer(context.Background(), &types.UpdateContainerRequest{ 78 Id: id, 79 Pid: "init", 80 Status: "paused", 81 }) 82 return err 83 } 84 85 func (cs *ContainerdSuite) ResumeContainer(id string) error { 86 _, err := cs.grpcClient.UpdateContainer(context.Background(), &types.UpdateContainerRequest{ 87 Id: id, 88 Pid: "init", 89 Status: "running", 90 }) 91 return err 92 } 93 94 func (cs *ContainerdSuite) GetContainerStats(id string) (*types.StatsResponse, error) { 95 stats, err := cs.grpcClient.Stats(context.Background(), &types.StatsRequest{ 96 Id: id, 97 }) 98 return stats, err 99 } 100 101 type stdio struct { 102 stdin string 103 stdout string 104 stderr string 105 stdinf *os.File 106 stdoutf *os.File 107 stderrf *os.File 108 stdoutBuffer bytes.Buffer 109 stderrBuffer bytes.Buffer 110 } 111 112 type ContainerProcess struct { 113 containerID string 114 pid string 115 bundle *Bundle 116 io stdio 117 eventsCh chan *types.Event 118 cs *ContainerdSuite 119 hasExited bool 120 } 121 122 func (c *ContainerProcess) openIo() (err error) { 123 defer func() { 124 if err != nil { 125 c.Cleanup() 126 } 127 }() 128 129 c.io.stdinf, err = os.OpenFile(c.io.stdin, os.O_RDWR, 0) 130 if err != nil { 131 return err 132 } 133 134 c.io.stdoutf, err = os.OpenFile(c.io.stdout, os.O_RDWR, 0) 135 if err != nil { 136 return err 137 } 138 go io.Copy(&c.io.stdoutBuffer, c.io.stdoutf) 139 140 c.io.stderrf, err = os.OpenFile(c.io.stderr, os.O_RDWR, 0) 141 if err != nil { 142 return err 143 } 144 go io.Copy(&c.io.stderrBuffer, c.io.stderrf) 145 146 return nil 147 } 148 149 func (c *ContainerProcess) GetEventsChannel() chan *types.Event { 150 return c.eventsCh 151 } 152 153 func (c *ContainerProcess) GetNextEvent() *types.Event { 154 if c.hasExited { 155 return nil 156 } 157 158 e := <-c.eventsCh 159 160 if e.Type == "exit" && e.Pid == c.pid { 161 c.Cleanup() 162 c.hasExited = true 163 close(c.eventsCh) 164 } 165 166 return e 167 } 168 169 func (c *ContainerProcess) CloseStdin() error { 170 _, err := c.cs.grpcClient.UpdateProcess(context.Background(), &types.UpdateProcessRequest{ 171 Id: c.containerID, 172 Pid: c.pid, 173 CloseStdin: true, 174 }) 175 return err 176 } 177 178 func (c *ContainerProcess) Cleanup() { 179 for _, f := range []*os.File{ 180 c.io.stdinf, 181 c.io.stdoutf, 182 c.io.stderrf, 183 } { 184 if f != nil { 185 f.Close() 186 f = nil 187 } 188 } 189 } 190 191 func NewContainerProcess(cs *ContainerdSuite, bundle *Bundle, cid, pid string) (c *ContainerProcess, err error) { 192 c = &ContainerProcess{ 193 containerID: cid, 194 pid: "init", 195 bundle: bundle, 196 eventsCh: make(chan *types.Event, 8), 197 cs: cs, 198 hasExited: false, 199 } 200 201 for name, path := range map[string]*string{ 202 "stdin": &c.io.stdin, 203 "stdout": &c.io.stdout, 204 "stderr": &c.io.stderr, 205 } { 206 *path = filepath.Join(bundle.Path, "io", cid+"-"+pid+"-"+name) 207 if err = unix.Mkfifo(*path, 0755); err != nil && !os.IsExist(err) { 208 return nil, err 209 } 210 } 211 212 if err = c.openIo(); err != nil { 213 return nil, err 214 } 215 216 return c, nil 217 } 218 219 func (cs *ContainerdSuite) StartContainerWithEventFilter(id, bundleName string, filter func(*types.Event)) (c *ContainerProcess, err error) { 220 bundle := GetBundle(bundleName) 221 if bundle == nil { 222 return nil, fmt.Errorf("No such bundle '%s'", bundleName) 223 } 224 225 c, err = NewContainerProcess(cs, bundle, id, "init") 226 if err != nil { 227 return nil, err 228 } 229 230 r := &types.CreateContainerRequest{ 231 Id: id, 232 BundlePath: filepath.Join(cs.cwd, bundle.Path), 233 Stdin: filepath.Join(cs.cwd, c.io.stdin), 234 Stdout: filepath.Join(cs.cwd, c.io.stdout), 235 Stderr: filepath.Join(cs.cwd, c.io.stderr), 236 } 237 238 if filter == nil { 239 filter = func(event *types.Event) { 240 c.eventsCh <- event 241 } 242 } 243 244 cs.SetContainerEventFilter(id, filter) 245 246 if _, err := cs.grpcClient.CreateContainer(context.Background(), r); err != nil { 247 c.Cleanup() 248 return nil, err 249 } 250 251 return c, nil 252 } 253 254 func (cs *ContainerdSuite) StartContainer(id, bundleName string) (c *ContainerProcess, err error) { 255 return cs.StartContainerWithEventFilter(id, bundleName, nil) 256 } 257 258 func (cs *ContainerdSuite) RunContainer(id, bundleName string) (c *ContainerProcess, err error) { 259 c, err = cs.StartContainer(id, bundleName) 260 if err != nil { 261 return nil, err 262 } 263 264 for { 265 e := c.GetNextEvent() 266 if e.Type == "exit" && e.Pid == "init" { 267 break 268 } 269 } 270 271 return c, err 272 } 273 274 func (cs *ContainerdSuite) AddProcessToContainer(init *ContainerProcess, pid, cwd string, env, args []string, uid, gid uint32) (c *ContainerProcess, err error) { 275 c, err = NewContainerProcess(cs, init.bundle, init.containerID, pid) 276 if err != nil { 277 return nil, err 278 } 279 280 pr := &types.AddProcessRequest{ 281 Id: init.containerID, 282 Pid: pid, 283 Args: args, 284 Cwd: cwd, 285 Env: env, 286 User: &types.User{ 287 Uid: uid, 288 Gid: gid, 289 }, 290 Stdin: filepath.Join(cs.cwd, c.io.stdin), 291 Stdout: filepath.Join(cs.cwd, c.io.stdout), 292 Stderr: filepath.Join(cs.cwd, c.io.stderr), 293 } 294 295 _, err = cs.grpcClient.AddProcess(context.Background(), pr) 296 if err != nil { 297 c.Cleanup() 298 return nil, err 299 } 300 301 return c, nil 302 } 303 304 type containerSorter struct { 305 c []*types.Container 306 } 307 308 func (s *containerSorter) Len() int { 309 return len(s.c) 310 } 311 312 func (s *containerSorter) Swap(i, j int) { 313 s.c[i], s.c[j] = s.c[j], s.c[i] 314 } 315 316 func (s *containerSorter) Less(i, j int) bool { 317 return s.c[i].Id < s.c[j].Id 318 } 319 320 func sortContainers(c []*types.Container) { 321 sort.Sort(&containerSorter{c}) 322 }