Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion libpod/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -1321,7 +1321,20 @@ func (c *Container) HostNetwork() bool {
// HasHealthCheck returns bool as to whether there is a health check
// defined for the container
func (c *Container) HasHealthCheck() bool {
return c.config.HealthCheckConfig != nil
// Consider a healthcheck present only when a HealthCheckConfig exists
// and the Test field contains a meaningful command. Treat an empty
// Test slice or the special ["NONE"] sentinel as "no healthcheck".
if c.config.HealthCheckConfig == nil {
return false
}
test := c.config.HealthCheckConfig.Test
if len(test) == 0 {
return false
}
if len(test) == 1 && strings.ToUpper(test[0]) == define.HealthConfigTestNone {
return false
}
return true
}

// HealthCheckConfig returns the command and timing attributes of the health check
Expand Down
36 changes: 36 additions & 0 deletions libpod/container_healthcheck_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//go:build !remote

package libpod

import (
"testing"

"github.com/stretchr/testify/assert"
manifest "go.podman.io/image/v5/manifest"
)

func TestHasHealthCheckCases(t *testing.T) {
ctr := &Container{config: &ContainerConfig{}}

// nil HealthCheckConfig -> false
ctr.config.HealthCheckConfig = nil
assert.False(t, ctr.HasHealthCheck(), "nil HealthCheckConfig should not be considered a healthcheck")

// Test == nil -> false
ctr.config.HealthCheckConfig = &manifest.Schema2HealthConfig{Test: nil}
assert.False(t, ctr.HasHealthCheck(), "nil Test slice should not be considered a healthcheck")

// empty slice -> false
ctr.config.HealthCheckConfig = &manifest.Schema2HealthConfig{Test: []string{}}
assert.False(t, ctr.HasHealthCheck(), "empty Test slice should not be considered a healthcheck")

// NONE sentinel -> false (case-insensitive)
ctr.config.HealthCheckConfig = &manifest.Schema2HealthConfig{Test: []string{"NONE"}}
assert.False(t, ctr.HasHealthCheck(), "[\"NONE\"] sentinel should not be considered a healthcheck")
ctr.config.HealthCheckConfig = &manifest.Schema2HealthConfig{Test: []string{"none"}}
assert.False(t, ctr.HasHealthCheck(), "[\"none\"] sentinel should not be considered a healthcheck")

// valid CMD form -> true
ctr.config.HealthCheckConfig = &manifest.Schema2HealthConfig{Test: []string{"CMD-SHELL", "echo hi"}}
assert.True(t, ctr.HasHealthCheck(), "non-empty Test with command should be considered a healthcheck")
}
5 changes: 1 addition & 4 deletions libpod/container_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *define.Driver
data.OCIConfigPath = c.state.ConfigPath
}

// Check if healthcheck is not nil and --no-healthcheck option is not set.
// If --no-healthcheck is set Test will be always set to `[NONE]`, so the
// inspect status should be set to nil.
if c.config.HealthCheckConfig != nil && (len(c.config.HealthCheckConfig.Test) != 1 || c.config.HealthCheckConfig.Test[0] != "NONE") {
if c.HasHealthCheck() {
// This container has a healthcheck defined in it; we need to add its state
healthCheckState, err := c.readHealthCheckLog()
if err != nil {
Expand Down
5 changes: 1 addition & 4 deletions libpod/container_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -1310,10 +1310,7 @@ func (c *Container) start() error {
}
}

// Check if healthcheck is not nil and --no-healthcheck option is not set.
// If --no-healthcheck is set Test will be always set to `[NONE]` so no need
// to update status in such case.
if c.config.HealthCheckConfig != nil && (len(c.config.HealthCheckConfig.Test) != 1 || c.config.HealthCheckConfig.Test[0] != "NONE") {
if c.HasHealthCheck() {
if err := c.updateHealthStatus(define.HealthCheckStarting); err != nil {
return fmt.Errorf("update healthcheck status: %w", err)
}
Expand Down