github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/test/e2e/healthcheck_run_test.go (about) 1 package integration 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "time" 9 10 define "github.com/hanks177/podman/v4/libpod/define" 11 . "github.com/hanks177/podman/v4/test/utils" 12 . "github.com/onsi/ginkgo" 13 . "github.com/onsi/gomega" 14 . "github.com/onsi/gomega/gexec" 15 ) 16 17 var _ = Describe("Podman healthcheck run", func() { 18 var ( 19 tempdir string 20 err error 21 podmanTest *PodmanTestIntegration 22 ) 23 24 BeforeEach(func() { 25 tempdir, err = CreateTempDirInTempDir() 26 if err != nil { 27 os.Exit(1) 28 } 29 podmanTest = PodmanTestCreate(tempdir) 30 podmanTest.Setup() 31 }) 32 33 AfterEach(func() { 34 podmanTest.Cleanup() 35 f := CurrentGinkgoTestDescription() 36 timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) 37 _, _ = GinkgoWriter.Write([]byte(timedResult)) 38 39 }) 40 41 It("podman healthcheck run bogus container", func() { 42 session := podmanTest.Podman([]string{"healthcheck", "run", "foobar"}) 43 session.WaitWithDefaultTimeout() 44 Expect(session).To(ExitWithError()) 45 }) 46 47 It("podman disable healthcheck with --no-healthcheck on valid container", func() { 48 session := podmanTest.Podman([]string{"run", "-dt", "--no-healthcheck", "--name", "hc", healthcheck}) 49 session.WaitWithDefaultTimeout() 50 Expect(session).Should(Exit(0)) 51 hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 52 hc.WaitWithDefaultTimeout() 53 Expect(hc).Should(Exit(125)) 54 }) 55 56 It("podman disable healthcheck with --no-healthcheck must not show starting on status", func() { 57 session := podmanTest.Podman([]string{"run", "-dt", "--no-healthcheck", "--name", "hc", healthcheck}) 58 session.WaitWithDefaultTimeout() 59 Expect(session).Should(Exit(0)) 60 hc := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.State.Health.Status}}", "hc"}) 61 hc.WaitWithDefaultTimeout() 62 Expect(hc).Should(Exit(0)) 63 Expect(hc.OutputToString()).To(Not(ContainSubstring("starting"))) 64 }) 65 66 It("podman run healthcheck and logs should contain healthcheck output", func() { 67 session := podmanTest.Podman([]string{"run", "--name", "test-logs", "-dt", "--health-interval", "1s", "--health-cmd", "echo working", "busybox", "sleep", "3600"}) 68 session.WaitWithDefaultTimeout() 69 Expect(session).Should(Exit(0)) 70 71 // Buy a little time to get container running 72 for i := 0; i < 5; i++ { 73 hc := podmanTest.Podman([]string{"healthcheck", "run", "test-logs"}) 74 hc.WaitWithDefaultTimeout() 75 exitCode := hc.ExitCode() 76 if exitCode == 0 || i == 4 { 77 break 78 } 79 time.Sleep(1 * time.Second) 80 } 81 82 hc := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.State.Healthcheck.Log}}", "test-logs"}) 83 hc.WaitWithDefaultTimeout() 84 Expect(hc).Should(Exit(0)) 85 Expect(hc.OutputToString()).To(ContainSubstring("working")) 86 }) 87 88 It("podman healthcheck from image's config (not container config)", func() { 89 // Regression test for #12226: a health check may be defined in 90 // the container or the container-config of an image. 91 session := podmanTest.Podman([]string{"create", "--name", "hc", "quay.io/libpod/healthcheck:config-only", "ls"}) 92 session.WaitWithDefaultTimeout() 93 Expect(session).Should(Exit(0)) 94 hc := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.Config.Healthcheck}}", "hc"}) 95 hc.WaitWithDefaultTimeout() 96 Expect(hc).Should(Exit(0)) 97 Expect(hc.OutputToString()).To(Equal("{[CMD-SHELL curl -f http://localhost/ || exit 1] 0s 5m0s 3s 0}")) 98 }) 99 100 It("podman disable healthcheck with --health-cmd=none on valid container", func() { 101 session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "none", "--name", "hc", healthcheck}) 102 session.WaitWithDefaultTimeout() 103 Expect(session).Should(Exit(0)) 104 hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 105 hc.WaitWithDefaultTimeout() 106 Expect(hc).Should(Exit(125)) 107 }) 108 109 It("podman healthcheck on valid container", func() { 110 Skip("Extremely consistent flake - re-enable on debugging") 111 session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", healthcheck}) 112 session.WaitWithDefaultTimeout() 113 Expect(session).Should(Exit(0)) 114 115 exitCode := 999 116 117 // Buy a little time to get container running 118 for i := 0; i < 5; i++ { 119 hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 120 hc.WaitWithDefaultTimeout() 121 exitCode = hc.ExitCode() 122 if exitCode == 0 || i == 4 { 123 break 124 } 125 time.Sleep(1 * time.Second) 126 } 127 Expect(exitCode).To(Equal(0)) 128 129 ps := podmanTest.Podman([]string{"ps"}) 130 ps.WaitWithDefaultTimeout() 131 Expect(ps).Should(Exit(0)) 132 Expect(ps.OutputToString()).To(ContainSubstring("(healthy)")) 133 }) 134 135 It("podman healthcheck that should fail", func() { 136 session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "quay.io/libpod/badhealthcheck:latest"}) 137 session.WaitWithDefaultTimeout() 138 Expect(session).Should(Exit(0)) 139 140 hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 141 hc.WaitWithDefaultTimeout() 142 Expect(hc).Should(Exit(1)) 143 }) 144 145 It("podman healthcheck on stopped container", func() { 146 session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", healthcheck, "ls"}) 147 session.WaitWithDefaultTimeout() 148 Expect(session).Should(Exit(0)) 149 150 hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 151 hc.WaitWithDefaultTimeout() 152 Expect(hc).Should(Exit(125)) 153 }) 154 155 It("podman healthcheck on container without healthcheck", func() { 156 session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", ALPINE, "top"}) 157 session.WaitWithDefaultTimeout() 158 Expect(session).Should(Exit(0)) 159 160 hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 161 hc.WaitWithDefaultTimeout() 162 Expect(hc).Should(Exit(125)) 163 }) 164 165 It("podman healthcheck should be starting", func() { 166 session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "--health-retries", "2", "--health-cmd", "ls /foo || exit 1", ALPINE, "top"}) 167 session.WaitWithDefaultTimeout() 168 Expect(session).Should(Exit(0)) 169 inspect := podmanTest.InspectContainer("hc") 170 Expect(inspect[0].State.Health).To(HaveField("Status", "starting")) 171 }) 172 173 It("podman healthcheck failed checks in start-period should not change status", func() { 174 session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "--health-start-period", "2m", "--health-retries", "2", "--health-cmd", "ls /foo || exit 1", ALPINE, "top"}) 175 session.WaitWithDefaultTimeout() 176 Expect(session).Should(Exit(0)) 177 178 hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 179 hc.WaitWithDefaultTimeout() 180 Expect(hc).Should(Exit(1)) 181 182 hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 183 hc.WaitWithDefaultTimeout() 184 Expect(hc).Should(Exit(1)) 185 186 hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 187 hc.WaitWithDefaultTimeout() 188 Expect(hc).Should(Exit(1)) 189 190 inspect := podmanTest.InspectContainer("hc") 191 Expect(inspect[0].State.Health).To(HaveField("Status", "starting")) 192 // test old podman compat (see #11645) 193 Expect(inspect[0].State.Healthcheck()).To(HaveField("Status", "starting")) 194 }) 195 196 It("podman healthcheck failed checks must reach retries before unhealthy ", func() { 197 session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "--health-retries", "2", "--health-cmd", "ls /foo || exit 1", ALPINE, "top"}) 198 session.WaitWithDefaultTimeout() 199 Expect(session).Should(Exit(0)) 200 201 hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 202 hc.WaitWithDefaultTimeout() 203 Expect(hc).Should(Exit(1)) 204 205 inspect := podmanTest.InspectContainer("hc") 206 Expect(inspect[0].State.Health).To(HaveField("Status", "starting")) 207 208 hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 209 hc.WaitWithDefaultTimeout() 210 Expect(hc).Should(Exit(1)) 211 212 inspect = podmanTest.InspectContainer("hc") 213 Expect(inspect[0].State.Health).To(HaveField("Status", define.HealthCheckUnhealthy)) 214 // test old podman compat (see #11645) 215 Expect(inspect[0].State.Healthcheck()).To(HaveField("Status", define.HealthCheckUnhealthy)) 216 }) 217 218 It("podman healthcheck good check results in healthy even in start-period", func() { 219 session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "--health-start-period", "2m", "--health-retries", "2", "--health-cmd", "ls || exit 1", ALPINE, "top"}) 220 session.WaitWithDefaultTimeout() 221 Expect(session).Should(Exit(0)) 222 223 hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 224 hc.WaitWithDefaultTimeout() 225 Expect(hc).Should(Exit(0)) 226 227 inspect := podmanTest.InspectContainer("hc") 228 Expect(inspect[0].State.Health).To(HaveField("Status", define.HealthCheckHealthy)) 229 }) 230 231 It("podman healthcheck unhealthy but valid arguments check", func() { 232 session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "--health-retries", "2", "--health-cmd", "[\"ls\", \"/foo\"]", ALPINE, "top"}) 233 session.WaitWithDefaultTimeout() 234 Expect(session).Should(Exit(0)) 235 236 hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 237 hc.WaitWithDefaultTimeout() 238 Expect(hc).Should(Exit(1)) 239 }) 240 241 It("podman healthcheck single healthy result changes failed to healthy", func() { 242 session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "--health-retries", "2", "--health-cmd", "ls /foo || exit 1", ALPINE, "top"}) 243 session.WaitWithDefaultTimeout() 244 Expect(session).Should(Exit(0)) 245 246 hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 247 hc.WaitWithDefaultTimeout() 248 Expect(hc).Should(Exit(1)) 249 250 inspect := podmanTest.InspectContainer("hc") 251 Expect(inspect[0].State.Health).To(HaveField("Status", "starting")) 252 253 hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 254 hc.WaitWithDefaultTimeout() 255 Expect(hc).Should(Exit(1)) 256 257 inspect = podmanTest.InspectContainer("hc") 258 Expect(inspect[0].State.Health).To(HaveField("Status", define.HealthCheckUnhealthy)) 259 260 foo := podmanTest.Podman([]string{"exec", "hc", "touch", "/foo"}) 261 foo.WaitWithDefaultTimeout() 262 Expect(foo).Should(Exit(0)) 263 264 hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) 265 hc.WaitWithDefaultTimeout() 266 Expect(hc).Should(Exit(0)) 267 268 inspect = podmanTest.InspectContainer("hc") 269 Expect(inspect[0].State.Health).To(HaveField("Status", define.HealthCheckHealthy)) 270 271 // Test podman ps --filter heath is working (#11687) 272 ps := podmanTest.Podman([]string{"ps", "--filter", "health=healthy"}) 273 ps.WaitWithDefaultTimeout() 274 Expect(ps).Should(Exit(0)) 275 Expect(ps.OutputToStringArray()).To(HaveLen(2)) 276 Expect(ps.OutputToString()).To(ContainSubstring("hc")) 277 }) 278 279 It("stopping and then starting a container with healthcheck cmd", func() { 280 session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "--health-cmd", "[\"ls\", \"/foo\"]", ALPINE, "top"}) 281 session.WaitWithDefaultTimeout() 282 Expect(session).Should(Exit(0)) 283 284 stop := podmanTest.Podman([]string{"stop", "-t0", "hc"}) 285 stop.WaitWithDefaultTimeout() 286 Expect(stop).Should(Exit(0)) 287 288 startAgain := podmanTest.Podman([]string{"start", "hc"}) 289 startAgain.WaitWithDefaultTimeout() 290 Expect(startAgain).Should(Exit(0)) 291 Expect(startAgain.OutputToString()).To(Equal("hc")) 292 Expect(startAgain.ErrorToString()).To(Equal("")) 293 }) 294 295 It("Verify default time is used and no utf-8 escapes", func() { 296 cwd, err := os.Getwd() 297 Expect(err).To(BeNil()) 298 299 podmanTest.AddImageToRWStore(ALPINE) 300 // Write target and fake files 301 targetPath, err := CreateTempDirInTempDir() 302 Expect(err).To(BeNil()) 303 containerfile := fmt.Sprintf(`FROM %s 304 HEALTHCHECK CMD ls -l / 2>&1`, ALPINE) 305 containerfilePath := filepath.Join(targetPath, "Containerfile") 306 err = ioutil.WriteFile(containerfilePath, []byte(containerfile), 0644) 307 Expect(err).To(BeNil()) 308 defer func() { 309 Expect(os.Chdir(cwd)).To(BeNil()) 310 Expect(os.RemoveAll(targetPath)).To(BeNil()) 311 }() 312 313 // make cwd as context root path 314 Expect(os.Chdir(targetPath)).To(BeNil()) 315 316 session := podmanTest.Podman([]string{"build", "--format", "docker", "-t", "test", "."}) 317 session.WaitWithDefaultTimeout() 318 Expect(session).Should(Exit(0)) 319 320 run := podmanTest.Podman([]string{"run", "-dt", "--name", "hctest", "test", "ls"}) 321 run.WaitWithDefaultTimeout() 322 Expect(run).Should(Exit(0)) 323 324 inspect := podmanTest.InspectContainer("hctest") 325 // Check to make sure a default time value was added 326 Expect(inspect[0].Config.Healthcheck.Timeout).To(BeNumerically("==", 30000000000)) 327 // Check to make sure a default time interval value was added 328 Expect(inspect[0].Config.Healthcheck.Interval).To(BeNumerically("==", 30000000000)) 329 // Check to make sure characters were not coerced to utf8 330 Expect(inspect[0].Config.Healthcheck).To(HaveField("Test", []string{"CMD-SHELL", "ls -l / 2>&1"})) 331 }) 332 })