mirror of
https://github.com/containers/podman.git
synced 2025-05-17 06:59:07 +08:00

New flags in a `podman update` can change the configuration of HealthCheck when the container is started, without having to restart or recreate the container. This can help determine why a given container suddenly started failing HealthCheck without interfering with the services it provides. For example, reconfigure HealthCheck to keep logs longer than the usual last X results, store logs to other destinations, etc. Fixes: https://issues.redhat.com/browse/RHEL-60561 Signed-off-by: Jan Rodák <hony.com@seznam.cz>
166 lines
5.4 KiB
Go
166 lines
5.4 KiB
Go
//go:build !remote
|
|
|
|
package libpod
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/containers/image/v5/manifest"
|
|
"github.com/containers/podman/v5/libpod/define"
|
|
"github.com/containers/podman/v5/pkg/specgenutil"
|
|
)
|
|
|
|
type HealthCheckConfig struct {
|
|
*manifest.Schema2HealthConfig
|
|
}
|
|
|
|
type StartupHealthCheckConfig struct {
|
|
*define.StartupHealthCheck
|
|
}
|
|
|
|
type IHealthCheckConfig interface {
|
|
SetTo(config *ContainerConfig)
|
|
IsStartup() bool
|
|
IsNil() bool
|
|
IsTimeChanged(oldInterval time.Duration) bool
|
|
GetInterval() time.Duration
|
|
SetCurrentConfigTo(healthCheckOptions *define.HealthCheckOptions)
|
|
IsHealthCheckCommandSet(updateHealthCheckConfig define.UpdateHealthCheckConfig) bool
|
|
SetNewHealthCheckOptions(updateHealthCheckConfig define.UpdateHealthCheckConfig, healthCheckOptions *define.HealthCheckOptions) bool
|
|
}
|
|
|
|
func (h *HealthCheckConfig) SetTo(config *ContainerConfig) {
|
|
config.HealthCheckConfig = h.Schema2HealthConfig
|
|
}
|
|
|
|
func (h *StartupHealthCheckConfig) SetTo(config *ContainerConfig) {
|
|
config.StartupHealthCheckConfig = h.StartupHealthCheck
|
|
}
|
|
|
|
func (h *HealthCheckConfig) IsNil() bool {
|
|
return h.Schema2HealthConfig == nil
|
|
}
|
|
|
|
func (h *StartupHealthCheckConfig) IsNil() bool {
|
|
return h.StartupHealthCheck == nil
|
|
}
|
|
|
|
func (h *HealthCheckConfig) IsStartup() bool {
|
|
return false
|
|
}
|
|
|
|
func (h *StartupHealthCheckConfig) IsStartup() bool {
|
|
return true
|
|
}
|
|
|
|
func (h *HealthCheckConfig) IsTimeChanged(oldInterval time.Duration) bool {
|
|
return h.Interval != oldInterval
|
|
}
|
|
|
|
func (h *StartupHealthCheckConfig) IsTimeChanged(oldInterval time.Duration) bool {
|
|
return h.Interval != oldInterval
|
|
}
|
|
|
|
func (h *HealthCheckConfig) GetInterval() time.Duration {
|
|
return h.Interval
|
|
}
|
|
|
|
func (h *StartupHealthCheckConfig) GetInterval() time.Duration {
|
|
return h.Interval
|
|
}
|
|
|
|
func (h *HealthCheckConfig) SetCurrentConfigTo(healthCheckOptions *define.HealthCheckOptions) {
|
|
healthCheckOptions.Cmd = strings.Join(h.Test, " ")
|
|
healthCheckOptions.Interval = h.Interval.String()
|
|
healthCheckOptions.Retries = h.Retries
|
|
healthCheckOptions.Timeout = h.Timeout.String()
|
|
healthCheckOptions.StartPeriod = h.StartPeriod.String()
|
|
}
|
|
|
|
func (h *StartupHealthCheckConfig) SetCurrentConfigTo(healthCheckOptions *define.HealthCheckOptions) {
|
|
healthCheckOptions.Cmd = strings.Join(h.Test, " ")
|
|
healthCheckOptions.Interval = h.Interval.String()
|
|
healthCheckOptions.Retries = h.Retries
|
|
healthCheckOptions.Timeout = h.Timeout.String()
|
|
healthCheckOptions.Successes = h.Successes
|
|
}
|
|
|
|
func (h *HealthCheckConfig) IsHealthCheckCommandSet(updateHealthCheckConfig define.UpdateHealthCheckConfig) bool {
|
|
return updateHealthCheckConfig.IsHealthCheckCommandSet(h.Schema2HealthConfig)
|
|
}
|
|
|
|
func (h *StartupHealthCheckConfig) IsHealthCheckCommandSet(updateHealthCheckConfig define.UpdateHealthCheckConfig) bool {
|
|
return updateHealthCheckConfig.IsStartupHealthCheckCommandSet(h.StartupHealthCheck)
|
|
}
|
|
|
|
func (h *HealthCheckConfig) SetNewHealthCheckOptions(updateHealthCheckConfig define.UpdateHealthCheckConfig, healthCheckOptions *define.HealthCheckOptions) bool {
|
|
return updateHealthCheckConfig.SetNewHealthCheckConfigTo(healthCheckOptions)
|
|
}
|
|
|
|
func (h *StartupHealthCheckConfig) SetNewHealthCheckOptions(updateHealthCheckConfig define.UpdateHealthCheckConfig, healthCheckOptions *define.HealthCheckOptions) bool {
|
|
return updateHealthCheckConfig.SetNewStartupHealthCheckConfigTo(healthCheckOptions)
|
|
}
|
|
|
|
func GetNewHealthCheckConfig(originalHealthCheckConfig IHealthCheckConfig, updateHealthCheckConfig define.UpdateHealthCheckConfig) (IHealthCheckConfig, bool, error) {
|
|
if originalHealthCheckConfig.IsHealthCheckCommandSet(updateHealthCheckConfig) {
|
|
return nil, false, errors.New("startup healthcheck command is not set")
|
|
}
|
|
|
|
healthCheckOptions := define.HealthCheckOptions{
|
|
Cmd: "",
|
|
Interval: define.DefaultHealthCheckInterval,
|
|
Retries: int(define.DefaultHealthCheckRetries),
|
|
Timeout: define.DefaultHealthCheckTimeout,
|
|
StartPeriod: define.DefaultHealthCheckStartPeriod,
|
|
Successes: 0,
|
|
}
|
|
|
|
if originalHealthCheckConfig.IsStartup() {
|
|
healthCheckOptions.Retries = 0
|
|
}
|
|
|
|
if !originalHealthCheckConfig.IsNil() {
|
|
originalHealthCheckConfig.SetCurrentConfigTo(&healthCheckOptions)
|
|
}
|
|
|
|
noHealthCheck := false
|
|
if updateHealthCheckConfig.NoHealthCheck != nil {
|
|
noHealthCheck = *updateHealthCheckConfig.NoHealthCheck
|
|
}
|
|
|
|
changed := originalHealthCheckConfig.SetNewHealthCheckOptions(updateHealthCheckConfig, &healthCheckOptions)
|
|
|
|
if noHealthCheck && changed {
|
|
return nil, false, errors.New("cannot specify both --no-healthcheck and other HealthCheck flags")
|
|
}
|
|
|
|
if noHealthCheck {
|
|
if originalHealthCheckConfig.IsStartup() {
|
|
return &StartupHealthCheckConfig{StartupHealthCheck: nil}, true, nil
|
|
}
|
|
return &HealthCheckConfig{Schema2HealthConfig: &manifest.Schema2HealthConfig{Test: []string{"NONE"}}}, true, nil
|
|
}
|
|
|
|
newHealthCheckConfig, err := specgenutil.MakeHealthCheckFromCli(
|
|
healthCheckOptions.Cmd,
|
|
healthCheckOptions.Interval,
|
|
uint(healthCheckOptions.Retries),
|
|
healthCheckOptions.Timeout,
|
|
healthCheckOptions.StartPeriod,
|
|
true,
|
|
)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
|
|
if originalHealthCheckConfig.IsStartup() {
|
|
newStartupHealthCheckConfig := new(define.StartupHealthCheck)
|
|
newStartupHealthCheckConfig.Schema2HealthConfig = *newHealthCheckConfig
|
|
newStartupHealthCheckConfig.Successes = healthCheckOptions.Successes
|
|
return &StartupHealthCheckConfig{StartupHealthCheck: newStartupHealthCheckConfig}, changed, nil
|
|
}
|
|
return &HealthCheckConfig{Schema2HealthConfig: newHealthCheckConfig}, changed, nil
|
|
}
|