diff --git a/libpod/healthcheck.go b/libpod/healthcheck.go index 437b2b45f9..f5f6838bfe 100644 --- a/libpod/healthcheck.go +++ b/libpod/healthcheck.go @@ -177,7 +177,9 @@ func (c *Container) runHealthCheck(ctx context.Context, isStartup bool) (define. if hcResult == define.HealthCheckNotDefined || hcResult == define.HealthCheckInternalError { return hcResult, logStatus, hcErr } - c.newContainerHealthCheckEvent(logStatus) + if c.runtime.config.Engine.HealthcheckEvents { + c.newContainerHealthCheckEvent(logStatus) + } return hcResult, logStatus, hcErr } diff --git a/test/e2e/healthcheck_run_test.go b/test/e2e/healthcheck_run_test.go index e6843845fe..808003edae 100644 --- a/test/e2e/healthcheck_run_test.go +++ b/test/e2e/healthcheck_run_test.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "path/filepath" + "strconv" "time" "github.com/containers/podman/v5/libpod/define" @@ -215,53 +216,75 @@ var _ = Describe("Podman healthcheck run", func() { Expect(hc).Should(Exit(1)) }) - It("podman healthcheck single healthy result changes failed to healthy", func() { - session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "--health-retries", "2", "--health-cmd", "ls /foo || exit 1", ALPINE, "top"}) - session.WaitWithDefaultTimeout() - Expect(session).Should(ExitCleanly()) + // Run this test with and without healthcheck events, even without events + // podman inspect and ps should still show accurate healthcheck results. + for _, hcEvent := range []bool{true, false} { + hcEvent := hcEvent + testName := "hc_events=" + strconv.FormatBool(hcEvent) + It("podman healthcheck single healthy result changes failed to healthy "+testName, func() { + if !hcEvent { + path := filepath.Join(podmanTest.TempDir, "containers.conf") + err := os.WriteFile(path, []byte("[engine]\nhealthcheck_events=false\n"), 0o644) + Expect(err).ToNot(HaveOccurred()) + err = os.Setenv("CONTAINERS_CONF_OVERRIDE", path) + Expect(err).ToNot(HaveOccurred()) + if IsRemote() { + podmanTest.StopRemoteService() + podmanTest.StartRemoteService() + } + } - hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) - hc.WaitWithDefaultTimeout() - Expect(hc).Should(Exit(1)) + session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "--health-retries", "2", "--health-cmd", "ls /foo || exit 1", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(ExitCleanly()) - inspect := podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Health).To(HaveField("Status", "starting")) + hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc).Should(Exit(1)) - hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) - hc.WaitWithDefaultTimeout() - Expect(hc).Should(Exit(1)) + inspect := podmanTest.InspectContainer("hc") + Expect(inspect[0].State.Health).To(HaveField("Status", "starting")) - inspect = podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Health).To(HaveField("Status", define.HealthCheckUnhealthy)) + hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc).Should(Exit(1)) - foo := podmanTest.Podman([]string{"exec", "hc", "touch", "/foo"}) - foo.WaitWithDefaultTimeout() - Expect(foo).Should(ExitCleanly()) + inspect = podmanTest.InspectContainer("hc") + Expect(inspect[0].State.Health).To(HaveField("Status", define.HealthCheckUnhealthy)) - hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) - hc.WaitWithDefaultTimeout() - Expect(hc).Should(ExitCleanly()) + foo := podmanTest.Podman([]string{"exec", "hc", "touch", "/foo"}) + foo.WaitWithDefaultTimeout() + Expect(foo).Should(ExitCleanly()) - inspect = podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Health).To(HaveField("Status", define.HealthCheckHealthy)) + hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc).Should(ExitCleanly()) - // Test that events generated have correct status (#19237) - events := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "event=health_status", "--since", "1m"}) - events.WaitWithDefaultTimeout() - Expect(events).Should(ExitCleanly()) - eventsOut := events.OutputToStringArray() - Expect(eventsOut).To(HaveLen(3)) - Expect(eventsOut[0]).To(ContainSubstring("health_status=starting")) - Expect(eventsOut[1]).To(ContainSubstring("health_status=unhealthy")) - Expect(eventsOut[2]).To(ContainSubstring("health_status=healthy")) + inspect = podmanTest.InspectContainer("hc") + Expect(inspect[0].State.Health).To(HaveField("Status", define.HealthCheckHealthy)) - // Test podman ps --filter health is working (#11687) - ps := podmanTest.Podman([]string{"ps", "--filter", "health=healthy"}) - ps.WaitWithDefaultTimeout() - Expect(ps).Should(ExitCleanly()) - Expect(ps.OutputToStringArray()).To(HaveLen(2)) - Expect(ps.OutputToString()).To(ContainSubstring("hc")) - }) + // Test that events generated have correct status (#19237) + events := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "event=health_status", "--since", "1m"}) + events.WaitWithDefaultTimeout() + Expect(events).Should(ExitCleanly()) + if hcEvent { + eventsOut := events.OutputToStringArray() + Expect(eventsOut).To(HaveLen(3)) + Expect(eventsOut[0]).To(ContainSubstring("health_status=starting")) + Expect(eventsOut[1]).To(ContainSubstring("health_status=unhealthy")) + Expect(eventsOut[2]).To(ContainSubstring("health_status=healthy")) + } else { + Expect(events.OutputToString()).To(BeEmpty()) + } + + // Test podman ps --filter health is working (#11687) + ps := podmanTest.Podman([]string{"ps", "--filter", "health=healthy"}) + ps.WaitWithDefaultTimeout() + Expect(ps).Should(ExitCleanly()) + Expect(ps.OutputToStringArray()).To(HaveLen(2)) + Expect(ps.OutputToString()).To(ContainSubstring("hc")) + }) + } It("hc logs do not include exec events", func() { session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "--health-cmd", "true", "--health-interval", "5s", "alpine", "sleep", "60"})