sync container state before reading the healthcheck

The health check result is stored in the container state. Since the
state can change or might not even be set we have to retrive the current
state before we try to read the health check result.

Fixes #11687

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
Paul Holzinger 2021-09-22 16:11:50 +02:00
parent 8e2d25e937
commit db44addf97
No known key found for this signature in database
GPG Key ID: EB145DD938A3CAF2
3 changed files with 19 additions and 6 deletions

View File

@ -151,7 +151,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *define.Driver
if c.config.HealthCheckConfig != nil { if c.config.HealthCheckConfig != nil {
// This container has a healthcheck defined in it; we need to add it's state // This container has a healthcheck defined in it; we need to add it's state
healthCheckState, err := c.GetHealthCheckLog() healthCheckState, err := c.getHealthCheckLog()
if err != nil { if err != nil {
// An error here is not considered fatal; no health state will be displayed // An error here is not considered fatal; no health state will be displayed
logrus.Error(err) logrus.Error(err)

View File

@ -162,7 +162,7 @@ func newHealthCheckLog(start, end time.Time, exitCode int, log string) define.He
// updatedHealthCheckStatus updates the health status of the container // updatedHealthCheckStatus updates the health status of the container
// in the healthcheck log // in the healthcheck log
func (c *Container) updateHealthStatus(status string) error { func (c *Container) updateHealthStatus(status string) error {
healthCheck, err := c.GetHealthCheckLog() healthCheck, err := c.getHealthCheckLog()
if err != nil { if err != nil {
return err return err
} }
@ -176,7 +176,7 @@ func (c *Container) updateHealthStatus(status string) error {
// UpdateHealthCheckLog parses the health check results and writes the log // UpdateHealthCheckLog parses the health check results and writes the log
func (c *Container) updateHealthCheckLog(hcl define.HealthCheckLog, inStartPeriod bool) error { func (c *Container) updateHealthCheckLog(hcl define.HealthCheckLog, inStartPeriod bool) error {
healthCheck, err := c.GetHealthCheckLog() healthCheck, err := c.getHealthCheckLog()
if err != nil { if err != nil {
return err return err
} }
@ -213,10 +213,11 @@ func (c *Container) healthCheckLogPath() string {
return filepath.Join(filepath.Dir(c.state.RunDir), "healthcheck.log") return filepath.Join(filepath.Dir(c.state.RunDir), "healthcheck.log")
} }
// GetHealthCheckLog returns HealthCheck results by reading the container's // getHealthCheckLog returns HealthCheck results by reading the container's
// health check log file. If the health check log file does not exist, then // health check log file. If the health check log file does not exist, then
// an empty healthcheck struct is returned // an empty healthcheck struct is returned
func (c *Container) GetHealthCheckLog() (define.HealthCheckResults, error) { // The caller should lock the container before this function is called.
func (c *Container) getHealthCheckLog() (define.HealthCheckResults, error) {
var healthCheck define.HealthCheckResults var healthCheck define.HealthCheckResults
if _, err := os.Stat(c.healthCheckLogPath()); os.IsNotExist(err) { if _, err := os.Stat(c.healthCheckLogPath()); os.IsNotExist(err) {
return healthCheck, nil return healthCheck, nil
@ -236,7 +237,12 @@ func (c *Container) HealthCheckStatus() (string, error) {
if !c.HasHealthCheck() { if !c.HasHealthCheck() {
return "", errors.Errorf("container %s has no defined healthcheck", c.ID()) return "", errors.Errorf("container %s has no defined healthcheck", c.ID())
} }
results, err := c.GetHealthCheckLog() c.lock.Lock()
defer c.lock.Unlock()
if err := c.syncContainer(); err != nil {
return "", err
}
results, err := c.getHealthCheckLog()
if err != nil { if err != nil {
return "", errors.Wrapf(err, "unable to get healthcheck log for %s", c.ID()) return "", errors.Wrapf(err, "unable to get healthcheck log for %s", c.ID())
} }

View File

@ -214,5 +214,12 @@ var _ = Describe("Podman healthcheck run", func() {
inspect = podmanTest.InspectContainer("hc") inspect = podmanTest.InspectContainer("hc")
Expect(inspect[0].State.Healthcheck.Status).To(Equal(define.HealthCheckHealthy)) Expect(inspect[0].State.Healthcheck.Status).To(Equal(define.HealthCheckHealthy))
// Test podman ps --filter heath is working (#11687)
ps := podmanTest.Podman([]string{"ps", "--filter", "health=healthy"})
ps.WaitWithDefaultTimeout()
Expect(ps).Should(Exit(0))
Expect(len(ps.OutputToStringArray())).To(Equal(2))
Expect(ps.OutputToString()).To(ContainSubstring("hc"))
}) })
}) })