add containers.conf healthcheck_events support

When the field is set to false we should never log healthcheck events.

Fixes https://issues.redhat.com/browse/RHEL-18987

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
Paul Holzinger
2024-04-19 12:04:23 +02:00
parent 33def2eea7
commit 2ae6d0d4dd
2 changed files with 64 additions and 39 deletions

View File

@ -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
}

View File

@ -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"})