From c836ffe5bce748f215d0649f052df026fc6d8d62 Mon Sep 17 00:00:00 2001 From: Milivoje Legenovic Date: Tue, 3 Aug 2021 13:48:07 +0200 Subject: Compat API: Fix healthcheck status and healthcheck config Fixes: - Do not show healthcheck status if not available or if container status is "created" (Docker behaviour) - Show healthcheck configuration if present (Config.Healthcheck) Tests: - Ensure State.Health is not present if container status is "created" - Ensure Config.Healthcheck is present and values correct - Ensure State.Health is present if container started Signed-off-by: Milivoje Legenovic --- pkg/api/handlers/compat/containers.go | 45 ++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 16 deletions(-) (limited to 'pkg/api') diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index 2a0a0b725..95c09ff0e 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -403,22 +403,24 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, state.Status = define.ContainerStateCreated.String() } - state.Health = &types.Health{ - Status: inspect.State.Healthcheck.Status, - FailingStreak: inspect.State.Healthcheck.FailingStreak, - } - - log := inspect.State.Healthcheck.Log + if l.HasHealthCheck() && state.Status != "created" { + state.Health = &types.Health{ + Status: inspect.State.Healthcheck.Status, + FailingStreak: inspect.State.Healthcheck.FailingStreak, + } - 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) + log := inspect.State.Healthcheck.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) + } } formatCapabilities(inspect.HostConfig.CapDrop) @@ -495,6 +497,17 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, exposedPorts[exposedPort] = struct{}{} } + var healthcheck *container.HealthConfig + if inspect.Config.Healthcheck != nil { + healthcheck = &container.HealthConfig{ + Test: inspect.Config.Healthcheck.Test, + Interval: inspect.Config.Healthcheck.Interval, + Timeout: inspect.Config.Healthcheck.Timeout, + StartPeriod: inspect.Config.Healthcheck.StartPeriod, + Retries: inspect.Config.Healthcheck.Retries, + } + } + config := container.Config{ Hostname: l.Hostname(), Domainname: inspect.Config.DomainName, @@ -508,7 +521,7 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, StdinOnce: inspect.Config.StdinOnce, Env: inspect.Config.Env, Cmd: l.Command(), - Healthcheck: nil, + Healthcheck: healthcheck, ArgsEscaped: false, Image: imageName, Volumes: nil, -- cgit v1.2.3-54-g00ecf From a82006160e6abbddc62f28999bca8865e5ea4806 Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Mon, 2 Aug 2021 15:18:54 -0700 Subject: Only support containers stats using cgroups v2 Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1988252 Signed-off-by: Jhon Honce --- pkg/api/handlers/libpod/containers_stats.go | 12 ++++++++++++ pkg/api/server/register_containers.go | 4 ++++ test/apiv2/20-containers.at | 10 ++++++++++ 3 files changed, 26 insertions(+) (limited to 'pkg/api') diff --git a/pkg/api/handlers/libpod/containers_stats.go b/pkg/api/handlers/libpod/containers_stats.go index 75c404d4f..22faab71f 100644 --- a/pkg/api/handlers/libpod/containers_stats.go +++ b/pkg/api/handlers/libpod/containers_stats.go @@ -7,8 +7,10 @@ import ( "github.com/containers/podman/v3/libpod" "github.com/containers/podman/v3/pkg/api/handlers/utils" + "github.com/containers/podman/v3/pkg/cgroups" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/domain/infra/abi" + "github.com/containers/podman/v3/pkg/rootless" "github.com/gorilla/schema" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -20,6 +22,16 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) decoder := r.Context().Value("decoder").(*schema.Decoder) + // Check if service is running rootless (cheap check) + if rootless.IsRootless() { + // if so, then verify cgroup v2 available (more expensive check) + if isV2, _ := cgroups.IsCgroup2UnifiedMode(); !isV2 { + msg := "Container stats resource only available for cgroup v2" + utils.Error(w, msg, http.StatusConflict, errors.New(msg)) + return + } + } + query := struct { Containers []string `schema:"containers"` Stream bool `schema:"stream"` diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go index 50e059ecc..89de84cce 100644 --- a/pkg/api/server/register_containers.go +++ b/pkg/api/server/register_containers.go @@ -1085,6 +1085,8 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // description: no error // 404: // $ref: "#/responses/NoSuchContainer" + // 409: + // $ref: "#/responses/ConflictError" // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name}/stats"), s.APIHandler(compat.StatsContainer)).Methods(http.MethodGet) @@ -1113,6 +1115,8 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // description: no error // 404: // $ref: "#/responses/NoSuchContainer" + // 409: + // $ref: "#/responses/ConflictError" // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/stats"), s.APIHandler(libpod.StatsContainer)).Methods(http.MethodGet) diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at index c5b2f5ec1..610d3e36d 100644 --- a/test/apiv2/20-containers.at +++ b/test/apiv2/20-containers.at @@ -65,6 +65,16 @@ t GET libpod/containers/json?last=1 200 \ cid=$(jq -r '.[0].Id' <<<"$output") +if root; then + t GET libpod/containers/stats?containers='[$cid]' 200 +else + if have_cgroupsv2; then + t GET libpod/containers/stats?containers='[$cid]' 200 + else + t GET libpod/containers/stats?containers='[$cid]' 409 + fi +fi + t DELETE libpod/containers/$cid 204 # Issue #6799: it should be possible to start a container, even w/o args. -- cgit v1.2.3-54-g00ecf