github.com/sameo/containerd@v0.2.8/integration-test/exec_test.go (about) 1 // +build !solaris 2 3 package main 4 5 import ( 6 "path/filepath" 7 "syscall" 8 "time" 9 10 "github.com/docker/containerd/api/grpc/types" 11 "github.com/docker/docker/pkg/integration/checker" 12 "github.com/go-check/check" 13 ) 14 15 func (cs *ContainerdSuite) TestBusyboxTopExecEcho(t *check.C) { 16 bundleName := "busybox-top" 17 if err := CreateBusyboxBundle(bundleName, []string{"top"}); err != nil { 18 t.Fatal(err) 19 } 20 21 var ( 22 err error 23 initp *ContainerProcess 24 echop *ContainerProcess 25 ) 26 27 containerID := "top" 28 initp, err = cs.StartContainer(containerID, bundleName) 29 t.Assert(err, checker.Equals, nil) 30 31 echop, err = cs.AddProcessToContainer(initp, "echo", "/", []string{"PATH=/bin"}, []string{"sh", "-c", "echo -n Ay Caramba! ; exit 1"}, 0, 0) 32 t.Assert(err, checker.Equals, nil) 33 34 for _, evt := range []types.Event{ 35 { 36 Type: "start-container", 37 Id: containerID, 38 Status: 0, 39 Pid: "", 40 }, 41 { 42 Type: "start-process", 43 Id: containerID, 44 Status: 0, 45 Pid: "echo", 46 }, 47 { 48 Type: "exit", 49 Id: containerID, 50 Status: 1, 51 Pid: "echo", 52 }, 53 } { 54 ch := initp.GetEventsChannel() 55 e := <-ch 56 evt.Timestamp = e.Timestamp 57 58 t.Assert(*e, checker.Equals, evt) 59 } 60 61 t.Assert(echop.io.stdoutBuffer.String(), checker.Equals, "Ay Caramba!") 62 } 63 64 func (cs *ContainerdSuite) TestBusyboxTopExecTop(t *check.C) { 65 bundleName := "busybox-top" 66 if err := CreateBusyboxBundle(bundleName, []string{"top"}); err != nil { 67 t.Fatal(err) 68 } 69 70 var ( 71 err error 72 initp *ContainerProcess 73 ) 74 75 containerID := "top" 76 initp, err = cs.StartContainer(containerID, bundleName) 77 t.Assert(err, checker.Equals, nil) 78 79 execID := "top1" 80 _, err = cs.AddProcessToContainer(initp, execID, "/", []string{"PATH=/usr/bin"}, []string{"top"}, 0, 0) 81 t.Assert(err, checker.Equals, nil) 82 83 for idx, evt := range []types.Event{ 84 { 85 Type: "start-container", 86 Id: containerID, 87 Status: 0, 88 Pid: "", 89 }, 90 { 91 Type: "start-process", 92 Id: containerID, 93 Status: 0, 94 Pid: execID, 95 }, 96 { 97 Type: "exit", 98 Id: containerID, 99 Status: 137, 100 Pid: execID, 101 }, 102 } { 103 ch := initp.GetEventsChannel() 104 e := <-ch 105 evt.Timestamp = e.Timestamp 106 t.Assert(*e, checker.Equals, evt) 107 if idx == 1 { 108 // Process Started, kill it 109 cs.SignalContainerProcess(containerID, "top1", uint32(syscall.SIGKILL)) 110 } 111 } 112 113 // Container should still be running 114 containers, err := cs.ListRunningContainers() 115 if err != nil { 116 t.Fatal(err) 117 } 118 t.Assert(len(containers), checker.Equals, 1) 119 t.Assert(containers[0].Id, checker.Equals, "top") 120 t.Assert(containers[0].Status, checker.Equals, "running") 121 t.Assert(containers[0].BundlePath, check.Equals, filepath.Join(cs.cwd, GetBundle(bundleName).Path)) 122 } 123 124 func (cs *ContainerdSuite) TestBusyboxTopExecTopKillInit(t *check.C) { 125 bundleName := "busybox-top" 126 if err := CreateBusyboxBundle(bundleName, []string{"top"}); err != nil { 127 t.Fatal(err) 128 } 129 130 var ( 131 err error 132 initp *ContainerProcess 133 ) 134 135 containerID := "top" 136 initp, err = cs.StartContainer(containerID, bundleName) 137 t.Assert(err, checker.Equals, nil) 138 139 execID := "top1" 140 _, err = cs.AddProcessToContainer(initp, execID, "/", []string{"PATH=/usr/bin"}, []string{"top"}, 0, 0) 141 t.Assert(err, checker.Equals, nil) 142 143 ch := initp.GetEventsChannel() 144 for _, evt := range []types.Event{ 145 { 146 Type: "start-container", 147 Id: containerID, 148 Status: 0, 149 Pid: "", 150 }, 151 { 152 Type: "start-process", 153 Id: containerID, 154 Status: 0, 155 Pid: execID, 156 }, 157 } { 158 e := <-ch 159 evt.Timestamp = e.Timestamp 160 t.Assert(*e, checker.Equals, evt) 161 } 162 163 cs.SignalContainerProcess(containerID, "init", uint32(syscall.SIGTERM)) 164 for i := 0; i < 2; i++ { 165 e := <-ch 166 switch e.Pid { 167 case "init": 168 evt := types.Event{ 169 Type: "exit", 170 Id: containerID, 171 Status: 143, 172 Pid: "init", 173 Timestamp: e.Timestamp, 174 } 175 t.Assert(*e, checker.Equals, evt) 176 case execID: 177 evt := types.Event{ 178 Type: "exit", 179 Id: containerID, 180 Status: 137, 181 Pid: execID, 182 Timestamp: e.Timestamp, 183 } 184 t.Assert(*e, checker.Equals, evt) 185 default: 186 t.Fatalf("Unexpected event %v", e) 187 } 188 } 189 190 } 191 192 func (cs *ContainerdSuite) TestBusyboxExecCreateDetachedChild(t *check.C) { 193 bundleName := "busybox-top" 194 if err := CreateBusyboxBundle(bundleName, []string{"top"}); err != nil { 195 t.Fatal(err) 196 } 197 198 var ( 199 err error 200 initp *ContainerProcess 201 ) 202 203 containerID := "top" 204 initp, err = cs.StartContainer(containerID, bundleName) 205 t.Assert(err, checker.Equals, nil) 206 207 ch := initp.GetEventsChannel() 208 for _, evt := range []types.Event{ 209 { 210 Type: "start-container", 211 Id: containerID, 212 Status: 0, 213 Pid: "", 214 }, 215 } { 216 e := <-ch 217 evt.Timestamp = e.Timestamp 218 t.Assert(*e, checker.Equals, evt) 219 } 220 221 execID := "sh-sleep" 222 _, err = cs.AddProcessToContainer(initp, execID, "/", []string{"PATH=/bin"}, []string{"sh", "-c", "sleep 1000 2>&- 1>&- 0<&- &"}, 0, 0) 223 t.Assert(err, checker.Equals, nil) 224 for _, evt := range []types.Event{ 225 { 226 Type: "start-process", 227 Id: containerID, 228 Status: 0, 229 Pid: execID, 230 }, 231 { 232 Type: "exit", 233 Id: containerID, 234 Status: 0, 235 Pid: execID, 236 }, 237 } { 238 e := <-ch 239 evt.Timestamp = e.Timestamp 240 t.Assert(*e, checker.Equals, evt) 241 } 242 243 // Check that sleep is still running 244 execOutput, err := cs.AddProcessToContainer(initp, "ps", "/", []string{"PATH=/bin"}, []string{"ps", "aux"}, 0, 0) 245 t.Assert(err, checker.Equals, nil) 246 t.Assert(execOutput.io.stdoutBuffer.String(), checker.Contains, "sleep 1000") 247 } 248 249 func (cs *ContainerdSuite) TestBusyboxExecCreateAttachedChild(t *check.C) { 250 bundleName := "busybox-top" 251 if err := CreateBusyboxBundle(bundleName, []string{"top"}); err != nil { 252 t.Fatal(err) 253 } 254 255 var ( 256 err error 257 initp *ContainerProcess 258 ) 259 260 containerID := "top" 261 initp, err = cs.StartContainer(containerID, bundleName) 262 t.Assert(err, checker.Equals, nil) 263 264 ch := initp.GetEventsChannel() 265 for _, evt := range []types.Event{ 266 { 267 Type: "start-container", 268 Id: containerID, 269 Status: 0, 270 Pid: "", 271 }, 272 } { 273 e := <-ch 274 evt.Timestamp = e.Timestamp 275 t.Assert(*e, checker.Equals, evt) 276 } 277 278 doneCh := make(chan struct{}) 279 go func() { 280 execID := "sh-sleep" 281 _, err = cs.AddProcessToContainer(initp, execID, "/", []string{"PATH=/bin"}, []string{"sh", "-c", "sleep 5 &"}, 0, 0) 282 t.Assert(err, checker.Equals, nil) 283 for _, evt := range []types.Event{ 284 { 285 Type: "start-process", 286 Id: containerID, 287 Status: 0, 288 Pid: execID, 289 }, 290 { 291 Type: "exit", 292 Id: containerID, 293 Status: 0, 294 Pid: execID, 295 }, 296 } { 297 e := <-ch 298 evt.Timestamp = e.Timestamp 299 t.Assert(*e, checker.Equals, evt) 300 } 301 close(doneCh) 302 }() 303 304 select { 305 case <-doneCh: 306 break 307 case <-time.After(8 * time.Second): 308 t.Fatal("exec did not exit within 5 seconds") 309 } 310 } 311 312 func (cs *ContainerdSuite) TestBusyboxRestoreDeadExec(t *check.C) { 313 bundleName := "busybox-top" 314 if err := CreateBusyboxBundle(bundleName, []string{"top"}); err != nil { 315 t.Fatal(err) 316 } 317 318 var ( 319 err error 320 initp *ContainerProcess 321 ) 322 323 containerID := "top" 324 initp, err = cs.StartContainer(containerID, bundleName) 325 t.Assert(err, checker.Equals, nil) 326 327 ch := initp.GetEventsChannel() 328 for _, evt := range []types.Event{ 329 { 330 Type: "start-container", 331 Id: containerID, 332 Status: 0, 333 Pid: "", 334 }, 335 } { 336 e := <-ch 337 evt.Timestamp = e.Timestamp 338 t.Assert(*e, checker.Equals, evt) 339 } 340 341 createCh := make(chan struct{}) 342 killCh := make(chan struct{}) 343 doneCh := make(chan struct{}) 344 restartCh := make(chan struct{}) 345 go func() { 346 execID := "sleep" 347 p, err := cs.AddProcessToContainer(initp, execID, "/", []string{"PATH=/bin"}, []string{"sleep", "10"}, 0, 0) 348 t.Assert(err, checker.Equals, nil) 349 for idx, evt := range []types.Event{ 350 { 351 Type: "start-process", 352 Id: containerID, 353 Status: 0, 354 Pid: execID, 355 }, 356 { 357 Type: "exit", 358 Id: containerID, 359 Status: 137, 360 Pid: execID, 361 }, 362 } { 363 e := <-ch 364 evt.Timestamp = e.Timestamp 365 t.Assert(*e, checker.Equals, evt) 366 if idx == 0 { 367 close(createCh) 368 <-killCh 369 syscall.Kill(int(p.systemPid), syscall.SIGKILL) 370 close(restartCh) 371 } 372 } 373 close(doneCh) 374 }() 375 376 // wait for sleep to be created 377 <-createCh 378 // stop containerd 379 cs.StopDaemon(false) 380 // notify go routine to go ahead and kill the sleep exec 381 close(killCh) 382 // wait for the kill signal to have been sent 383 <-restartCh 384 if err := cs.StartDaemon(); err != nil { 385 t.Fatal(err) 386 } 387 // wait a tiny bit more just in case 388 time.Sleep(100 * time.Millisecond) 389 390 select { 391 case <-doneCh: 392 break 393 case <-time.After(8 * time.Second): 394 t.Fatal("exec did not exit within 5 seconds") 395 } 396 }