Skip to content

Commit

Permalink
Return nil health when inspecting containers without healthchecks
Browse files Browse the repository at this point in the history
When inspecting a container that does not define any health check, the health field should return nil. This matches docker behavior.

Signed-off-by: Ashley Cui <acui@redhat.com>
  • Loading branch information
ashley-cui committed Jan 27, 2024
1 parent 4bef652 commit 8e8f3fc
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 44 deletions.
6 changes: 5 additions & 1 deletion libpod/container_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package libpod
import (
"errors"
"fmt"
"reflect"
"strings"

"github.com/containers/podman/v4/libpod/define"
Expand Down Expand Up @@ -196,7 +197,10 @@ func (c *Container) getContainerInspectData(size bool, driverData *define.Driver
// An error here is not considered fatal; no health state will be displayed
logrus.Error(err)
} else {
data.State.Health = healthCheckState
if reflect.DeepEqual(healthCheckState, define.HealthCheckResults{}) {
data.State.Health = &healthCheckState
}
data.State.Health = nil
}
}

Expand Down
48 changes: 24 additions & 24 deletions libpod/define/container_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,34 +206,34 @@ type InspectMount struct {
// Docker, but here we see more fields that are unused (nonsensical in the
// context of Libpod).
type InspectContainerState struct {
OciVersion string `json:"OciVersion"`
Status string `json:"Status"`
Running bool `json:"Running"`
Paused bool `json:"Paused"`
Restarting bool `json:"Restarting"` // TODO
OOMKilled bool `json:"OOMKilled"`
Dead bool `json:"Dead"`
Pid int `json:"Pid"`
ConmonPid int `json:"ConmonPid,omitempty"`
ExitCode int32 `json:"ExitCode"`
Error string `json:"Error"` // TODO
StartedAt time.Time `json:"StartedAt"`
FinishedAt time.Time `json:"FinishedAt"`
Health HealthCheckResults `json:"Health,omitempty"`
Checkpointed bool `json:"Checkpointed,omitempty"`
CgroupPath string `json:"CgroupPath,omitempty"`
CheckpointedAt time.Time `json:"CheckpointedAt,omitempty"`
RestoredAt time.Time `json:"RestoredAt,omitempty"`
CheckpointLog string `json:"CheckpointLog,omitempty"`
CheckpointPath string `json:"CheckpointPath,omitempty"`
RestoreLog string `json:"RestoreLog,omitempty"`
Restored bool `json:"Restored,omitempty"`
StoppedByUser bool `json:"StoppedByUser,omitempty"`
OciVersion string `json:"OciVersion"`
Status string `json:"Status"`
Running bool `json:"Running"`
Paused bool `json:"Paused"`
Restarting bool `json:"Restarting"` // TODO
OOMKilled bool `json:"OOMKilled"`
Dead bool `json:"Dead"`
Pid int `json:"Pid"`
ConmonPid int `json:"ConmonPid,omitempty"`
ExitCode int32 `json:"ExitCode"`
Error string `json:"Error"` // TODO
StartedAt time.Time `json:"StartedAt"`
FinishedAt time.Time `json:"FinishedAt"`
Health *HealthCheckResults `json:"Health,omitempty"`
Checkpointed bool `json:"Checkpointed,omitempty"`
CgroupPath string `json:"CgroupPath,omitempty"`
CheckpointedAt time.Time `json:"CheckpointedAt,omitempty"`
RestoredAt time.Time `json:"RestoredAt,omitempty"`
CheckpointLog string `json:"CheckpointLog,omitempty"`
CheckpointPath string `json:"CheckpointPath,omitempty"`
RestoreLog string `json:"RestoreLog,omitempty"`
Restored bool `json:"Restored,omitempty"`
StoppedByUser bool `json:"StoppedByUser,omitempty"`
}

// Healthcheck returns the HealthCheckResults. This is used for old podman compat
// to make the "Healthcheck" key available in the go template.
func (s *InspectContainerState) Healthcheck() HealthCheckResults {
func (s *InspectContainerState) Healthcheck() *HealthCheckResults {
return s.Health
}

Expand Down
32 changes: 16 additions & 16 deletions pkg/api/handlers/compat/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,22 +442,22 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON,
}

if l.HasHealthCheck() && state.Status != "created" {
state.Health = &types.Health{
Status: inspect.State.Health.Status,
FailingStreak: inspect.State.Health.FailingStreak,
}

log := inspect.State.Health.Log

for _, item := range log {
res := &types.HealthcheckResult{}
s, _ := time.Parse(time.RFC3339Nano, item.Start)
e, _ := time.Parse(time.RFC3339Nano, item.End)
res.Start = s
res.End = e
res.ExitCode = item.ExitCode
res.Output = item.Output
state.Health.Log = append(state.Health.Log, res)
state.Health = &types.Health{}
if inspect.State.Health != nil {
state.Health.Status = inspect.State.Health.Status
state.Health.FailingStreak = inspect.State.Health.FailingStreak
log := inspect.State.Health.Log

for _, item := range log {
res := &types.HealthcheckResult{}
s, _ := time.Parse(time.RFC3339Nano, item.Start)
e, _ := time.Parse(time.RFC3339Nano, item.End)
res.Start = s
res.End = e
res.ExitCode = item.ExitCode
res.Output = item.Output
state.Health.Log = append(state.Health.Log, res)
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/apiv2/python/rest_api/test_v2_0_0_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def test_inspect(self):
self.assertEqual(r.status_code, 200, r.text)
self.assertId(r.content)
out = r.json()
self.assertIsNotNone(out["State"].get("Health"))
self.assertIsNone(out["State"].get("Health"))
self.assertListEqual(["CMD", "pidof", "top"], out["Config"]["Healthcheck"]["Test"])
self.assertEqual(5000000000, out["Config"]["Healthcheck"]["Interval"])
self.assertEqual(2000000000, out["Config"]["Healthcheck"]["Timeout"])
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/healthcheck_run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ var _ = Describe("Podman healthcheck run", func() {
session := podmanTest.Podman([]string{"run", "-dt", "--no-healthcheck", "--name", "hc", HEALTHCHECK_IMAGE})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
hc := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.State.Health.Status}}", "hc"})
hc := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.State.Health}}", "hc"})
hc.WaitWithDefaultTimeout()
Expect(hc).Should(ExitCleanly())
Expect(hc.OutputToString()).To(Not(ContainSubstring("starting")))
Expect(hc.OutputToString()).To(Equal("<nil>"))
})

It("podman run healthcheck and logs should contain healthcheck output", func() {
Expand Down

0 comments on commit 8e8f3fc

Please sign in to comment.