github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/bindings/test/containers_test.go (about) 1 package test_bindings 2 3 import ( 4 "net/http" 5 "strconv" 6 "strings" 7 "time" 8 9 "github.com/containers/libpod/libpod/define" 10 "github.com/containers/libpod/pkg/bindings" 11 "github.com/containers/libpod/pkg/bindings/containers" 12 "github.com/containers/libpod/pkg/specgen" 13 "github.com/containers/libpod/test/utils" 14 . "github.com/onsi/ginkgo" 15 . "github.com/onsi/gomega" 16 "github.com/onsi/gomega/gexec" 17 ) 18 19 var _ = Describe("Podman containers ", func() { 20 var ( 21 bt *bindingTest 22 s *gexec.Session 23 err error 24 ) 25 26 BeforeEach(func() { 27 bt = newBindingTest() 28 bt.RestoreImagesFromCache() 29 s = bt.startAPIService() 30 time.Sleep(1 * time.Second) 31 err := bt.NewConnection() 32 Expect(err).To(BeNil()) 33 }) 34 35 AfterEach(func() { 36 s.Kill() 37 bt.cleanup() 38 }) 39 40 It("podman pause a bogus container", func() { 41 // Pausing bogus container should return 404 42 err = containers.Pause(bt.conn, "foobar") 43 Expect(err).ToNot(BeNil()) 44 code, _ := bindings.CheckResponseCode(err) 45 Expect(code).To(BeNumerically("==", http.StatusNotFound)) 46 }) 47 48 It("podman unpause a bogus container", func() { 49 // Unpausing bogus container should return 404 50 err = containers.Unpause(bt.conn, "foobar") 51 Expect(err).ToNot(BeNil()) 52 code, _ := bindings.CheckResponseCode(err) 53 Expect(code).To(BeNumerically("==", http.StatusNotFound)) 54 }) 55 56 It("podman pause a running container by name", func() { 57 // Pausing by name should work 58 var name = "top" 59 _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 60 Expect(err).To(BeNil()) 61 err = containers.Pause(bt.conn, name) 62 Expect(err).To(BeNil()) 63 64 // Ensure container is paused 65 data, err := containers.Inspect(bt.conn, name, nil) 66 Expect(err).To(BeNil()) 67 Expect(data.State.Status).To(Equal("paused")) 68 }) 69 70 It("podman pause a running container by id", func() { 71 // Pausing by id should work 72 var name = "top" 73 cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 74 Expect(err).To(BeNil()) 75 err = containers.Pause(bt.conn, cid) 76 Expect(err).To(BeNil()) 77 78 // Ensure container is paused 79 data, err := containers.Inspect(bt.conn, cid, nil) 80 Expect(err).To(BeNil()) 81 Expect(data.State.Status).To(Equal("paused")) 82 }) 83 84 It("podman unpause a running container by name", func() { 85 // Unpausing by name should work 86 var name = "top" 87 _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 88 Expect(err).To(BeNil()) 89 err = containers.Pause(bt.conn, name) 90 Expect(err).To(BeNil()) 91 err = containers.Unpause(bt.conn, name) 92 Expect(err).To(BeNil()) 93 94 // Ensure container is unpaused 95 data, err := containers.Inspect(bt.conn, name, nil) 96 Expect(err).To(BeNil()) 97 Expect(data.State.Status).To(Equal("running")) 98 }) 99 100 It("podman unpause a running container by ID", func() { 101 // Unpausing by ID should work 102 var name = "top" 103 _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 104 Expect(err).To(BeNil()) 105 // Pause by name 106 err = containers.Pause(bt.conn, name) 107 //paused := "paused" 108 //_, err = containers.Wait(bt.conn, cid, &paused) 109 //Expect(err).To(BeNil()) 110 err = containers.Unpause(bt.conn, name) 111 Expect(err).To(BeNil()) 112 113 // Ensure container is unpaused 114 data, err := containers.Inspect(bt.conn, name, nil) 115 Expect(err).To(BeNil()) 116 Expect(data.State.Status).To(Equal("running")) 117 }) 118 119 It("podman pause a paused container by name", func() { 120 // Pausing a paused container by name should fail 121 var name = "top" 122 _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 123 Expect(err).To(BeNil()) 124 err = containers.Pause(bt.conn, name) 125 Expect(err).To(BeNil()) 126 err = containers.Pause(bt.conn, name) 127 Expect(err).ToNot(BeNil()) 128 code, _ := bindings.CheckResponseCode(err) 129 Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) 130 }) 131 132 It("podman pause a paused container by id", func() { 133 // Pausing a paused container by id should fail 134 var name = "top" 135 cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 136 Expect(err).To(BeNil()) 137 err = containers.Pause(bt.conn, cid) 138 Expect(err).To(BeNil()) 139 err = containers.Pause(bt.conn, cid) 140 Expect(err).ToNot(BeNil()) 141 code, _ := bindings.CheckResponseCode(err) 142 Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) 143 }) 144 145 It("podman pause a stopped container by name", func() { 146 // Pausing a stopped container by name should fail 147 var name = "top" 148 _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 149 Expect(err).To(BeNil()) 150 err = containers.Stop(bt.conn, name, nil) 151 Expect(err).To(BeNil()) 152 err = containers.Pause(bt.conn, name) 153 Expect(err).ToNot(BeNil()) 154 code, _ := bindings.CheckResponseCode(err) 155 Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) 156 }) 157 158 It("podman pause a stopped container by id", func() { 159 // Pausing a stopped container by id should fail 160 var name = "top" 161 cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 162 Expect(err).To(BeNil()) 163 err = containers.Stop(bt.conn, cid, nil) 164 Expect(err).To(BeNil()) 165 err = containers.Pause(bt.conn, cid) 166 Expect(err).ToNot(BeNil()) 167 code, _ := bindings.CheckResponseCode(err) 168 Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) 169 }) 170 171 It("podman remove a paused container by id without force", func() { 172 // Removing a paused container without force should fail 173 var name = "top" 174 cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 175 Expect(err).To(BeNil()) 176 err = containers.Pause(bt.conn, cid) 177 Expect(err).To(BeNil()) 178 err = containers.Remove(bt.conn, cid, &bindings.PFalse, &bindings.PFalse) 179 Expect(err).ToNot(BeNil()) 180 code, _ := bindings.CheckResponseCode(err) 181 Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) 182 }) 183 184 It("podman remove a paused container by id with force", func() { 185 // FIXME: Skip on F31 and later 186 host := utils.GetHostDistributionInfo() 187 osVer, err := strconv.Atoi(host.Version) 188 Expect(err).To(BeNil()) 189 if host.Distribution == "fedora" && osVer >= 31 { 190 Skip("FIXME: https://github.com/containers/libpod/issues/5325") 191 } 192 193 // Removing a paused container with force should work 194 var name = "top" 195 cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 196 Expect(err).To(BeNil()) 197 err = containers.Pause(bt.conn, cid) 198 Expect(err).To(BeNil()) 199 err = containers.Remove(bt.conn, cid, &bindings.PTrue, &bindings.PFalse) 200 Expect(err).To(BeNil()) 201 }) 202 203 It("podman stop a paused container by name", func() { 204 // Stopping a paused container by name should fail 205 var name = "top" 206 _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 207 Expect(err).To(BeNil()) 208 err = containers.Pause(bt.conn, name) 209 Expect(err).To(BeNil()) 210 err = containers.Stop(bt.conn, name, nil) 211 Expect(err).ToNot(BeNil()) 212 code, _ := bindings.CheckResponseCode(err) 213 Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) 214 }) 215 216 It("podman stop a paused container by id", func() { 217 // Stopping a paused container by id should fail 218 var name = "top" 219 cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 220 Expect(err).To(BeNil()) 221 err = containers.Pause(bt.conn, cid) 222 Expect(err).To(BeNil()) 223 err = containers.Stop(bt.conn, cid, nil) 224 Expect(err).ToNot(BeNil()) 225 code, _ := bindings.CheckResponseCode(err) 226 Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) 227 }) 228 229 It("podman stop a running container by name", func() { 230 // Stopping a running container by name should work 231 var name = "top" 232 _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 233 Expect(err).To(BeNil()) 234 err = containers.Stop(bt.conn, name, nil) 235 Expect(err).To(BeNil()) 236 237 // Ensure container is stopped 238 data, err := containers.Inspect(bt.conn, name, nil) 239 Expect(err).To(BeNil()) 240 Expect(isStopped(data.State.Status)).To(BeTrue()) 241 }) 242 243 It("podman stop a running container by ID", func() { 244 // Stopping a running container by ID should work 245 var name = "top" 246 cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 247 Expect(err).To(BeNil()) 248 err = containers.Stop(bt.conn, cid, nil) 249 Expect(err).To(BeNil()) 250 251 // Ensure container is stopped 252 data, err := containers.Inspect(bt.conn, name, nil) 253 Expect(err).To(BeNil()) 254 Expect(isStopped(data.State.Status)).To(BeTrue()) 255 }) 256 257 It("podman wait no condition", func() { 258 var ( 259 name = "top" 260 exitCode int32 = -1 261 ) 262 _, err := containers.Wait(bt.conn, "foobar", nil) 263 Expect(err).ToNot(BeNil()) 264 code, _ := bindings.CheckResponseCode(err) 265 Expect(code).To(BeNumerically("==", http.StatusNotFound)) 266 267 errChan := make(chan error) 268 _, err = bt.RunTopContainer(&name, nil, nil) 269 Expect(err).To(BeNil()) 270 go func() { 271 exitCode, err = containers.Wait(bt.conn, name, nil) 272 errChan <- err 273 close(errChan) 274 }() 275 err = containers.Stop(bt.conn, name, nil) 276 Expect(err).To(BeNil()) 277 wait := <-errChan 278 Expect(wait).To(BeNil()) 279 Expect(exitCode).To(BeNumerically("==", 143)) 280 }) 281 282 It("podman wait to pause|unpause condition", func() { 283 var ( 284 name = "top" 285 exitCode int32 = -1 286 pause = define.ContainerStatePaused 287 running = define.ContainerStateRunning 288 ) 289 errChan := make(chan error) 290 _, err := bt.RunTopContainer(&name, nil, nil) 291 Expect(err).To(BeNil()) 292 go func() { 293 exitCode, err = containers.Wait(bt.conn, name, &pause) 294 errChan <- err 295 close(errChan) 296 }() 297 err = containers.Pause(bt.conn, name) 298 Expect(err).To(BeNil()) 299 wait := <-errChan 300 Expect(wait).To(BeNil()) 301 Expect(exitCode).To(BeNumerically("==", -1)) 302 303 errChan = make(chan error) 304 go func() { 305 _, waitErr := containers.Wait(bt.conn, name, &running) 306 errChan <- waitErr 307 close(errChan) 308 }() 309 err = containers.Unpause(bt.conn, name) 310 Expect(err).To(BeNil()) 311 unPausewait := <-errChan 312 Expect(unPausewait).To(BeNil()) 313 Expect(exitCode).To(BeNumerically("==", -1)) 314 }) 315 316 It("run healthcheck", func() { 317 bt.runPodman([]string{"run", "-d", "--name", "hc", "--health-interval", "disable", "--health-retries", "2", "--health-cmd", "ls / || exit 1", alpine.name, "top"}) 318 319 // bogus name should result in 404 320 _, err := containers.RunHealthCheck(bt.conn, "foobar") 321 Expect(err).ToNot(BeNil()) 322 code, _ := bindings.CheckResponseCode(err) 323 Expect(code).To(BeNumerically("==", http.StatusNotFound)) 324 325 // a container that has no healthcheck should be a 409 326 var name = "top" 327 bt.RunTopContainer(&name, &bindings.PFalse, nil) 328 _, err = containers.RunHealthCheck(bt.conn, name) 329 Expect(err).ToNot(BeNil()) 330 code, _ = bindings.CheckResponseCode(err) 331 Expect(code).To(BeNumerically("==", http.StatusConflict)) 332 333 // TODO for the life of me, i cannot get this to work. maybe another set 334 // of eyes will 335 // successful healthcheck 336 //status := "healthy" 337 //for i:=0; i < 10; i++ { 338 // result, err := containers.RunHealthCheck(connText, "hc") 339 // Expect(err).To(BeNil()) 340 // if result.Status != "healthy" { 341 // fmt.Println("Healthcheck container still starting, retrying in 1 second") 342 // time.Sleep(1 * time.Second) 343 // continue 344 // } 345 // status = result.Status 346 // break 347 //} 348 //Expect(status).To(Equal("healthy")) 349 350 // TODO enable this when wait is working 351 // healthcheck on a stopped container should be a 409 352 //err = containers.Stop(connText, "hc", nil) 353 //Expect(err).To(BeNil()) 354 //_, err = containers.Wait(connText, "hc") 355 //Expect(err).To(BeNil()) 356 //_, err = containers.RunHealthCheck(connText, "hc") 357 //code, _ = bindings.CheckResponseCode(err) 358 //Expect(code).To(BeNumerically("==", http.StatusConflict)) 359 }) 360 361 It("logging", func() { 362 stdoutChan := make(chan string, 10) 363 s := specgen.NewSpecGenerator(alpine.name) 364 s.Terminal = true 365 s.Command = []string{"date", "-R"} 366 r, err := containers.CreateWithSpec(bt.conn, s) 367 Expect(err).To(BeNil()) 368 err = containers.Start(bt.conn, r.ID, nil) 369 Expect(err).To(BeNil()) 370 371 _, err = containers.Wait(bt.conn, r.ID, nil) 372 Expect(err).To(BeNil()) 373 374 opts := containers.LogOptions{Stdout: &bindings.PTrue, Follow: &bindings.PTrue} 375 go func() { 376 containers.Logs(bt.conn, r.ID, opts, stdoutChan, nil) 377 }() 378 o := <-stdoutChan 379 o = strings.ReplaceAll(o, "\r", "") 380 _, err = time.Parse(time.RFC1123Z, o) 381 Expect(err).To(BeNil()) 382 }) 383 384 It("podman top", func() { 385 var name = "top" 386 cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 387 Expect(err).To(BeNil()) 388 389 // By name 390 _, err = containers.Top(bt.conn, name, nil) 391 Expect(err).To(BeNil()) 392 393 // By id 394 _, err = containers.Top(bt.conn, cid, nil) 395 Expect(err).To(BeNil()) 396 397 // With descriptors 398 output, err := containers.Top(bt.conn, cid, []string{"user,pid,hpid"}) 399 Expect(err).To(BeNil()) 400 header := strings.Split(output[0], "\t") 401 for _, d := range []string{"USER", "PID", "HPID"} { 402 Expect(d).To(BeElementOf(header)) 403 } 404 405 // With bogus ID 406 _, err = containers.Top(bt.conn, "IdoNotExist", nil) 407 Expect(err).ToNot(BeNil()) 408 409 // With bogus descriptors 410 _, err = containers.Top(bt.conn, cid, []string{"Me,Neither"}) 411 Expect(err).To(BeNil()) 412 }) 413 414 It("podman bogus container does not exist in local storage", func() { 415 // Bogus container existence check should fail 416 containerExists, err := containers.Exists(bt.conn, "foobar") 417 Expect(err).To(BeNil()) 418 Expect(containerExists).To(BeFalse()) 419 }) 420 421 It("podman container exists in local storage by name", func() { 422 // Container existence check by name should work 423 var name = "top" 424 _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 425 Expect(err).To(BeNil()) 426 containerExists, err := containers.Exists(bt.conn, name) 427 Expect(err).To(BeNil()) 428 Expect(containerExists).To(BeTrue()) 429 }) 430 431 It("podman container exists in local storage by ID", func() { 432 // Container existence check by ID should work 433 var name = "top" 434 cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 435 Expect(err).To(BeNil()) 436 containerExists, err := containers.Exists(bt.conn, cid) 437 Expect(err).To(BeNil()) 438 Expect(containerExists).To(BeTrue()) 439 }) 440 441 It("podman container exists in local storage by short ID", func() { 442 // Container existence check by short ID should work 443 var name = "top" 444 cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 445 Expect(err).To(BeNil()) 446 containerExists, err := containers.Exists(bt.conn, cid[0:12]) 447 Expect(err).To(BeNil()) 448 Expect(containerExists).To(BeTrue()) 449 }) 450 451 It("podman kill bogus container", func() { 452 // Killing bogus container should return 404 453 err := containers.Kill(bt.conn, "foobar", "SIGTERM") 454 Expect(err).ToNot(BeNil()) 455 code, _ := bindings.CheckResponseCode(err) 456 Expect(code).To(BeNumerically("==", http.StatusNotFound)) 457 }) 458 459 It("podman kill a running container by name with SIGINT", func() { 460 // Killing a running container should work 461 var name = "top" 462 _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 463 Expect(err).To(BeNil()) 464 err = containers.Kill(bt.conn, name, "SIGINT") 465 Expect(err).To(BeNil()) 466 _, err = containers.Exists(bt.conn, name) 467 Expect(err).To(BeNil()) 468 }) 469 470 It("podman kill a running container by ID with SIGTERM", func() { 471 // Killing a running container by ID should work 472 var name = "top" 473 cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 474 Expect(err).To(BeNil()) 475 err = containers.Kill(bt.conn, cid, "SIGTERM") 476 Expect(err).To(BeNil()) 477 _, err = containers.Exists(bt.conn, cid) 478 Expect(err).To(BeNil()) 479 }) 480 481 It("podman kill a running container by ID with SIGKILL", func() { 482 // Killing a running container by ID with TERM should work 483 var name = "top" 484 cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 485 Expect(err).To(BeNil()) 486 err = containers.Kill(bt.conn, cid, "SIGKILL") 487 Expect(err).To(BeNil()) 488 }) 489 490 It("podman kill a running container by bogus signal", func() { 491 //Killing a running container by bogus signal should fail 492 var name = "top" 493 cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil) 494 Expect(err).To(BeNil()) 495 err = containers.Kill(bt.conn, cid, "foobar") 496 Expect(err).ToNot(BeNil()) 497 code, _ := bindings.CheckResponseCode(err) 498 Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) 499 }) 500 501 It("podman kill latest container with SIGTERM", func() { 502 // Killing latest container should work 503 var name1 = "first" 504 var name2 = "second" 505 var latestContainers = 1 506 _, err := bt.RunTopContainer(&name1, &bindings.PFalse, nil) 507 Expect(err).To(BeNil()) 508 _, err = bt.RunTopContainer(&name2, &bindings.PFalse, nil) 509 Expect(err).To(BeNil()) 510 containerLatestList, err := containers.List(bt.conn, nil, nil, &latestContainers, nil, nil, nil) 511 Expect(err).To(BeNil()) 512 err = containers.Kill(bt.conn, containerLatestList[0].Names[0], "SIGTERM") 513 Expect(err).To(BeNil()) 514 }) 515 516 It("container init on a bogus container", func() { 517 err := containers.ContainerInit(bt.conn, "doesnotexist") 518 Expect(err).ToNot(BeNil()) 519 code, _ := bindings.CheckResponseCode(err) 520 Expect(code).To(BeNumerically("==", http.StatusNotFound)) 521 }) 522 523 It("container init", func() { 524 s := specgen.NewSpecGenerator(alpine.name) 525 ctr, err := containers.CreateWithSpec(bt.conn, s) 526 Expect(err).To(BeNil()) 527 err = containers.ContainerInit(bt.conn, ctr.ID) 528 Expect(err).To(BeNil()) 529 // trying to init again should be an error 530 err = containers.ContainerInit(bt.conn, ctr.ID) 531 Expect(err).ToNot(BeNil()) 532 }) 533 534 })