Skip to content

Commit a2718bf

Browse files
committed
Fix HealthCheck log destination, count, and size defaults
GoLang sets unset values to the default value of the type. This means that the destination of the log is an empty string and the count and size are set to 0. However, this means that size and count are unbounded, and this is not the default behavior. Fixes: containers#25473 Signed-off-by: Jan Rodák <[email protected]>
1 parent d398062 commit a2718bf

File tree

17 files changed

+95
-66
lines changed

17 files changed

+95
-66
lines changed

libpod/container.go

+21
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,27 @@ func (c *Container) HealthCheckConfig() *manifest.Schema2HealthConfig {
12911291
return c.config.HealthCheckConfig
12921292
}
12931293

1294+
func (c *Container) HealthCheckLogDestination() string {
1295+
if c.config.HealthLogDestination == nil {
1296+
return define.DefaultHealthCheckLocalDestination
1297+
}
1298+
return *c.config.HealthLogDestination
1299+
}
1300+
1301+
func (c *Container) HealthCheckMaxLogCount() uint {
1302+
if c.config.HealthMaxLogCount == nil {
1303+
return define.DefaultHealthMaxLogCount
1304+
}
1305+
return *c.config.HealthMaxLogCount
1306+
}
1307+
1308+
func (c *Container) HealthCheckMaxLogSize() uint {
1309+
if c.config.HealthMaxLogSize == nil {
1310+
return define.DefaultHealthMaxLogSize
1311+
}
1312+
return *c.config.HealthMaxLogSize
1313+
}
1314+
12941315
// AutoRemove indicates whether the container will be removed after it is executed
12951316
func (c *Container) AutoRemove() bool {
12961317
spec := c.config.Spec

libpod/container_config.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -416,13 +416,16 @@ type ContainerMiscConfig struct {
416416
// HealthCheckOnFailureAction defines an action to take once the container turns unhealthy.
417417
HealthCheckOnFailureAction define.HealthCheckOnFailureAction `json:"healthcheck_on_failure_action"`
418418
// HealthLogDestination defines the destination where the log is stored
419-
HealthLogDestination string `json:"healthLogDestination,omitempty"`
419+
// Nil value means the default value (local).
420+
HealthLogDestination *string `json:"healthLogDestination,omitempty"`
420421
// HealthMaxLogCount is maximum number of attempts in the HealthCheck log file.
421422
// ('0' value means an infinite number of attempts in the log file)
422-
HealthMaxLogCount uint `json:"healthMaxLogCount,omitempty"`
423+
// Nil value means the default value (5).
424+
HealthMaxLogCount *uint `json:"healthMaxLogCount,omitempty"`
423425
// HealthMaxLogSize is the maximum length in characters of stored HealthCheck log
424426
// ("0" value means an infinite log length)
425-
HealthMaxLogSize uint `json:"healthMaxLogSize,omitempty"`
427+
// Nil value means the default value (500).
428+
HealthMaxLogSize *uint `json:"healthMaxLogSize,omitempty"`
426429
// StartupHealthCheckConfig is the configuration of the startup
427430
// healthcheck for the container. This will run before the regular HC
428431
// runs, and when it passes the regular HC will be activated.

libpod/container_inspect.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -437,11 +437,11 @@ func (c *Container) generateInspectContainerConfig(spec *spec.Spec) *define.Insp
437437

438438
ctrConfig.HealthcheckOnFailureAction = c.config.HealthCheckOnFailureAction.String()
439439

440-
ctrConfig.HealthLogDestination = c.config.HealthLogDestination
440+
ctrConfig.HealthLogDestination = c.HealthCheckLogDestination()
441441

442-
ctrConfig.HealthMaxLogCount = c.config.HealthMaxLogCount
442+
ctrConfig.HealthMaxLogCount = c.HealthCheckMaxLogCount()
443443

444-
ctrConfig.HealthMaxLogSize = c.config.HealthMaxLogSize
444+
ctrConfig.HealthMaxLogSize = c.HealthCheckMaxLogSize()
445445

446446
ctrConfig.CreateCommand = c.config.CreateCommand
447447

libpod/container_internal.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -2970,15 +2970,15 @@ func (c *Container) updateGlobalHealthCheckConfiguration(globalOptions define.Gl
29702970
}
29712971

29722972
if globalOptions.HealthMaxLogCount != nil {
2973-
c.config.HealthMaxLogCount = *globalOptions.HealthMaxLogCount
2973+
c.config.HealthMaxLogCount = globalOptions.HealthMaxLogCount
29742974
}
29752975

29762976
if globalOptions.HealthMaxLogSize != nil {
2977-
c.config.HealthMaxLogSize = *globalOptions.HealthMaxLogSize
2977+
c.config.HealthMaxLogSize = globalOptions.HealthMaxLogSize
29782978
}
29792979

29802980
if globalOptions.HealthLogDestination != nil {
2981-
dest, err := define.GetValidHealthCheckDestination(*globalOptions.HealthLogDestination)
2981+
dest, err := define.GetValidHealthCheckDestination(globalOptions.HealthLogDestination)
29822982
if err != nil {
29832983
return err
29842984
}

libpod/define/healthchecks.go

+16-10
Original file line numberDiff line numberDiff line change
@@ -292,37 +292,43 @@ func (u *UpdateHealthCheckConfig) SetNewHealthCheckConfigTo(healthCheckOptions *
292292
return changed
293293
}
294294

295-
func GetValidHealthCheckDestination(destination string) (string, error) {
296-
if destination == HealthCheckEventsLoggerDestination || destination == DefaultHealthCheckLocalDestination {
295+
func GetValidHealthCheckDestination(destination *string) (*string, error) {
296+
if destination == nil {
297+
defaultPath := DefaultHealthCheckLocalDestination
298+
return &defaultPath, nil
299+
}
300+
301+
if *destination == HealthCheckEventsLoggerDestination || *destination == DefaultHealthCheckLocalDestination {
297302
return destination, nil
298303
}
299304

300-
fileInfo, err := os.Stat(destination)
305+
path := *destination
306+
fileInfo, err := os.Stat(path)
301307
if err != nil {
302-
return "", fmt.Errorf("HealthCheck Log '%s' destination error: %w", destination, err)
308+
return nil, fmt.Errorf("HealthCheck Log '%s' destination error: %w", path, err)
303309
}
304310
mode := fileInfo.Mode()
305311
if !mode.IsDir() {
306-
return "", fmt.Errorf("HealthCheck Log '%s' destination must be directory", destination)
312+
return nil, fmt.Errorf("HealthCheck Log '%s' destination must be directory", path)
307313
}
308314

309-
absPath, err := filepath.Abs(destination)
315+
absPath, err := filepath.Abs(path)
310316
if err != nil {
311-
return "", err
317+
return nil, err
312318
}
313-
return absPath, nil
319+
return &absPath, nil
314320
}
315321

316322
func (u *UpdateHealthCheckConfig) GetNewGlobalHealthCheck() (GlobalHealthCheckOptions, error) {
317323
globalOptions := GlobalHealthCheckOptions{}
318324

319325
healthLogDestination := u.HealthLogDestination
320326
if u.HealthLogDestination != nil {
321-
dest, err := GetValidHealthCheckDestination(*u.HealthLogDestination)
327+
dest, err := GetValidHealthCheckDestination(u.HealthLogDestination)
322328
if err != nil {
323329
return GlobalHealthCheckOptions{}, err
324330
}
325-
healthLogDestination = &dest
331+
healthLogDestination = dest
326332
}
327333
globalOptions.HealthLogDestination = healthLogDestination
328334

libpod/events.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func (c *Container) newContainerEventWithInspectData(status events.Status, healt
4949
e.Image = c.config.RootfsImageName
5050
e.Type = events.Container
5151
e.HealthStatus = healthCheckResult.Status
52-
if c.config.HealthLogDestination == define.HealthCheckEventsLoggerDestination {
52+
if c.HealthCheckLogDestination() == define.HealthCheckEventsLoggerDestination {
5353
if len(healthCheckResult.Log) > 0 {
5454
logData, err := json.Marshal(healthCheckResult.Log[len(healthCheckResult.Log)-1])
5555
if err != nil {

libpod/healthcheck.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ func (c *Container) runHealthCheck(ctx context.Context, isStartup bool) (define.
152152
}
153153

154154
eventLog := output.String()
155-
if c.config.HealthMaxLogSize != 0 && len(eventLog) > int(c.config.HealthMaxLogSize) {
156-
eventLog = eventLog[:c.config.HealthMaxLogSize]
155+
if c.HealthCheckMaxLogSize() != 0 && len(eventLog) > int(c.HealthCheckMaxLogSize()) {
156+
eventLog = eventLog[:c.HealthCheckMaxLogSize()]
157157
}
158158

159159
if timeEnd.Sub(timeStart) > c.HealthCheckConfig().Timeout {
@@ -166,7 +166,7 @@ func (c *Container) runHealthCheck(ctx context.Context, isStartup bool) (define.
166166

167167
healthCheckResult, err := c.updateHealthCheckLog(hcl, hcResult, inStartPeriod, isStartup)
168168
if err != nil {
169-
return hcResult, "", fmt.Errorf("unable to update health check log %s for %s: %w", c.config.HealthLogDestination, c.ID(), err)
169+
return hcResult, "", fmt.Errorf("unable to update health check log %s for %s: %w", c.getHealthCheckLogDestination(), c.ID(), err)
170170
}
171171

172172
// Write HC event with appropriate status as the last thing before we
@@ -399,7 +399,7 @@ func (c *Container) updateHealthCheckLog(hcl define.HealthCheckLog, hcResult def
399399
}
400400
}
401401
healthCheck.Log = append(healthCheck.Log, hcl)
402-
if c.config.HealthMaxLogCount != 0 && len(healthCheck.Log) > int(c.config.HealthMaxLogCount) {
402+
if c.HealthCheckMaxLogCount() != 0 && len(healthCheck.Log) > int(c.HealthCheckMaxLogCount()) {
403403
healthCheck.Log = healthCheck.Log[1:]
404404
}
405405
return healthCheck, c.writeHealthCheckLog(healthCheck)
@@ -415,11 +415,11 @@ func (c *Container) witeToFileHealthCheckResults(path string, result define.Heal
415415

416416
func (c *Container) getHealthCheckLogDestination() string {
417417
var destination string
418-
switch c.config.HealthLogDestination {
418+
switch c.HealthCheckLogDestination() {
419419
case define.DefaultHealthCheckLocalDestination, define.HealthCheckEventsLoggerDestination, "":
420420
destination = filepath.Join(filepath.Dir(c.state.RunDir), "healthcheck.log")
421421
default:
422-
destination = filepath.Join(c.config.HealthLogDestination, c.ID()+"-healthcheck.log")
422+
destination = filepath.Join(c.HealthCheckLogDestination(), c.ID()+"-healthcheck.log")
423423
}
424424
return destination
425425
}

libpod/options.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -1527,7 +1527,7 @@ func WithHealthCheck(healthCheck *manifest.Schema2HealthConfig) CtrCreateOption
15271527
}
15281528

15291529
// WithHealthCheckLogDestination adds the healthLogDestination to the container config
1530-
func WithHealthCheckLogDestination(destination string) CtrCreateOption {
1530+
func WithHealthCheckLogDestination(destination *string) CtrCreateOption {
15311531
return func(ctr *Container) error {
15321532
if ctr.valid {
15331533
return define.ErrCtrFinalized
@@ -1542,7 +1542,7 @@ func WithHealthCheckLogDestination(destination string) CtrCreateOption {
15421542
}
15431543

15441544
// WithHealthCheckMaxLogCount adds the healthMaxLogCount to the container config
1545-
func WithHealthCheckMaxLogCount(maxLogCount uint) CtrCreateOption {
1545+
func WithHealthCheckMaxLogCount(maxLogCount *uint) CtrCreateOption {
15461546
return func(ctr *Container) error {
15471547
if ctr.valid {
15481548
return define.ErrCtrFinalized
@@ -1553,7 +1553,7 @@ func WithHealthCheckMaxLogCount(maxLogCount uint) CtrCreateOption {
15531553
}
15541554

15551555
// WithHealthCheckMaxLogSize adds the healthMaxLogSize to the container config
1556-
func WithHealthCheckMaxLogSize(maxLogSize uint) CtrCreateOption {
1556+
func WithHealthCheckMaxLogSize(maxLogSize *uint) CtrCreateOption {
15571557
return func(ctr *Container) error {
15581558
if ctr.valid {
15591559
return define.ErrCtrFinalized

pkg/api/handlers/libpod/containers_create.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
3434
noHosts := conf.Containers.NoHosts
3535
privileged := conf.Containers.Privileged
3636

37+
defaultHealthLogDestination := define.DefaultHealthCheckLocalDestination
38+
defaultHealthLogCount := define.DefaultHealthMaxLogCount
39+
defaultHealthLogSize := define.DefaultHealthMaxLogSize
40+
3741
// we have to set the default before we decode to make sure the correct default is set when the field is unset
3842
sg := specgen.SpecGenerator{
3943
ContainerNetworkConfig: specgen.ContainerNetworkConfig{
@@ -44,7 +48,9 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
4448
Privileged: &privileged,
4549
},
4650
ContainerHealthCheckConfig: specgen.ContainerHealthCheckConfig{
47-
HealthLogDestination: define.DefaultHealthCheckLocalDestination,
51+
HealthLogDestination: &defaultHealthLogDestination,
52+
HealthMaxLogCount: &defaultHealthLogCount,
53+
HealthMaxLogSize: &defaultHealthLogSize,
4854
},
4955
}
5056

pkg/domain/entities/pods.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"strings"
66

77
commonFlag "github.com/containers/common/pkg/flag"
8+
"github.com/containers/podman/v5/libpod/define"
89
"github.com/containers/podman/v5/pkg/domain/entities/types"
910
"github.com/containers/podman/v5/pkg/specgen"
1011
"github.com/containers/podman/v5/pkg/util"
@@ -275,9 +276,12 @@ type ContainerCreateOptions struct {
275276

276277
func NewInfraContainerCreateOptions() ContainerCreateOptions {
277278
options := ContainerCreateOptions{
278-
IsInfra: true,
279-
ImageVolume: "anonymous",
280-
MemorySwappiness: -1,
279+
IsInfra: true,
280+
ImageVolume: "anonymous",
281+
MemorySwappiness: -1,
282+
HealthLogDestination: define.DefaultHealthCheckLocalDestination,
283+
HealthMaxLogCount: define.DefaultHealthMaxLogCount,
284+
HealthMaxLogSize: define.DefaultHealthMaxLogSize,
281285
}
282286
return options
283287
}

pkg/domain/infra/abi/containers.go

-4
Original file line numberDiff line numberDiff line change
@@ -1765,10 +1765,6 @@ func (ic *ContainerEngine) ContainerClone(ctx context.Context, ctrCloneOpts enti
17651765
spec.Name = generate.CheckName(ic.Libpod, n, true)
17661766
}
17671767

1768-
spec.HealthLogDestination = define.DefaultHealthCheckLocalDestination
1769-
spec.HealthMaxLogCount = define.DefaultHealthMaxLogCount
1770-
spec.HealthMaxLogSize = define.DefaultHealthMaxLogSize
1771-
17721768
rtSpec, spec, opts, err := generate.MakeContainer(context.Background(), ic.Libpod, spec, true, c)
17731769
if err != nil {
17741770
return nil, err

pkg/domain/infra/abi/generate.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,12 @@ func (ic *ContainerEngine) GenerateSpec(ctx context.Context, opts *entities.Gene
5959
} else if p, err := ic.Libpod.LookupPod(opts.ID); err == nil {
6060
pspec = &specgen.PodSpecGenerator{}
6161
pspec.Name = p.Name()
62-
_, err := generateUtils.PodConfigToSpec(ic.Libpod, pspec, &entities.ContainerCreateOptions{}, opts.ID)
62+
_, err := generateUtils.PodConfigToSpec(ic.Libpod, pspec,
63+
&entities.ContainerCreateOptions{
64+
HealthLogDestination: define.DefaultHealthCheckLocalDestination,
65+
HealthMaxLogCount: define.DefaultHealthMaxLogCount,
66+
HealthMaxLogSize: define.DefaultHealthMaxLogSize,
67+
}, opts.ID)
6368
if err != nil {
6469
return nil, err
6570
}

pkg/specgen/generate/kube/kube.go

-3
Original file line numberDiff line numberDiff line change
@@ -417,9 +417,6 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
417417
}
418418

419419
s.Annotations[define.KubeHealthCheckAnnotation] = "true"
420-
s.HealthLogDestination = define.DefaultHealthCheckLocalDestination
421-
s.HealthMaxLogCount = define.DefaultHealthMaxLogCount
422-
s.HealthMaxLogSize = define.DefaultHealthMaxLogSize
423420

424421
// Environment Variables
425422
envs := map[string]string{}

pkg/specgen/generate/pod_create.go

-5
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,6 @@ func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (_ *libpod.Pod, finalErr e
8686
p.PodSpecGen.InfraContainerSpec.ResourceLimits = nil
8787
p.PodSpecGen.InfraContainerSpec.WeightDevice = nil
8888

89-
// Set default for HealthCheck
90-
p.PodSpecGen.InfraContainerSpec.HealthLogDestination = define.DefaultHealthCheckLocalDestination
91-
p.PodSpecGen.InfraContainerSpec.HealthMaxLogCount = define.DefaultHealthMaxLogCount
92-
p.PodSpecGen.InfraContainerSpec.HealthMaxLogSize = define.DefaultHealthMaxLogSize
93-
9489
rtSpec, spec, opts, err := MakeContainer(context.Background(), rt, p.PodSpecGen.InfraContainerSpec, false, nil)
9590
if err != nil {
9691
return nil, err

pkg/specgen/specgen.go

+9-16
Original file line numberDiff line numberDiff line change
@@ -602,14 +602,17 @@ type ContainerHealthCheckConfig struct {
602602
// Requires that HealthConfig be set.
603603
// Optional.
604604
StartupHealthConfig *define.StartupHealthCheck `json:"startupHealthConfig,omitempty"`
605-
// HealthLogDestination defines the destination where the log is stored
606-
HealthLogDestination string `json:"healthLogDestination,omitempty"`
605+
// HealthLogDestination defines the destination where the log is stored.
606+
// Nil value means the default value (local).
607+
HealthLogDestination *string `json:"healthLogDestination,omitempty"`
607608
// HealthMaxLogCount is maximum number of attempts in the HealthCheck log file.
608-
// ('0' value means an infinite number of attempts in the log file)
609-
HealthMaxLogCount uint `json:"healthMaxLogCount,omitempty"`
609+
// ('0' value means an infinite number of attempts in the log file).
610+
// Nil value means the default value (5).
611+
HealthMaxLogCount *uint `json:"healthMaxLogCount,omitempty"`
610612
// HealthMaxLogSize is the maximum length in characters of stored HealthCheck log
611-
// ("0" value means an infinite log length)
612-
HealthMaxLogSize uint `json:"healthMaxLogSize,omitempty"`
613+
// ("0" value means an infinite log length).
614+
// Nil value means the default value (500).
615+
HealthMaxLogSize *uint `json:"healthMaxLogSize,omitempty"`
613616
}
614617

615618
// SpecGenerator creates an OCI spec and Libpod configuration options to create
@@ -682,11 +685,6 @@ func NewSpecGenerator(arg string, rootfs bool) *SpecGenerator {
682685
}
683686
return &SpecGenerator{
684687
ContainerStorageConfig: csc,
685-
ContainerHealthCheckConfig: ContainerHealthCheckConfig{
686-
HealthLogDestination: define.DefaultHealthCheckLocalDestination,
687-
HealthMaxLogCount: define.DefaultHealthMaxLogCount,
688-
HealthMaxLogSize: define.DefaultHealthMaxLogSize,
689-
},
690688
}
691689
}
692690

@@ -695,11 +693,6 @@ func NewSpecGeneratorWithRootfs(rootfs string) *SpecGenerator {
695693
csc := ContainerStorageConfig{Rootfs: rootfs}
696694
return &SpecGenerator{
697695
ContainerStorageConfig: csc,
698-
ContainerHealthCheckConfig: ContainerHealthCheckConfig{
699-
HealthLogDestination: define.DefaultHealthCheckLocalDestination,
700-
HealthMaxLogCount: define.DefaultHealthMaxLogCount,
701-
HealthMaxLogSize: define.DefaultHealthMaxLogSize,
702-
},
703696
}
704697
}
705698

pkg/specgenutil/specgen.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -370,11 +370,11 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions
370370
}
371371
s.HealthCheckOnFailureAction = onFailureAction
372372

373-
s.HealthLogDestination = c.HealthLogDestination
373+
s.HealthLogDestination = &c.HealthLogDestination
374374

375-
s.HealthMaxLogCount = c.HealthMaxLogCount
375+
s.HealthMaxLogCount = &c.HealthMaxLogCount
376376

377-
s.HealthMaxLogSize = c.HealthMaxLogSize
377+
s.HealthMaxLogSize = &c.HealthMaxLogSize
378378

379379
if c.StartupHCCmd != "" {
380380
if c.NoHealthCheck {

test/apiv2/20-containers.at

+4-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,10 @@ t GET libpod/containers/${cid}/json 200 \
199199
.State.Running=false \
200200
.State.ExitCode=0 \
201201
.Config.Umask=0022 \
202-
.Config.CreateCommand=null
202+
.Config.CreateCommand=null \
203+
.Config.HealthLogDestination=local \
204+
.Config.HealthcheckMaxLogCount=5 \
205+
.Config.HealthcheckMaxLogSize=500
203206
t DELETE libpod/containers/$cid 200 .[0].Id=$cid
204207

205208
CNAME=myfoo

0 commit comments

Comments
 (0)