Better Probe builder

- we didn't get probe configuration from compose, it's now fixed
- the HealthCheck object is tricky because it overrides `time.Duration`,
  we are using specific initialization in NewProbeWithDuration
- it is easier to pass the ServiceConfig to NewProbeFromService
This commit is contained in:
2022-05-05 12:16:04 +02:00
parent bfe6738348
commit d72ab14400
2 changed files with 64 additions and 10 deletions

View File

@@ -471,14 +471,15 @@ func prepareProbes(name string, s types.ServiceConfig, container *helm.Container
// first, check if there is no label for the probe // first, check if there is no label for the probe
if check, ok := s.Labels[helm.LABEL_HEALTHCHECK]; ok { if check, ok := s.Labels[helm.LABEL_HEALTHCHECK]; ok {
check = strings.TrimSpace(check) check = strings.TrimSpace(check)
p := helm.NewProbeFromService(&s)
// get the port of the "url" check // get the port of the "url" check
if checkurl, err := url.Parse(check); err == nil { if checkurl, err := url.Parse(check); err == nil {
if err == nil { if err == nil {
container.LivenessProbe = buildProtoProbe(checkurl) container.LivenessProbe = buildProtoProbe(p, checkurl)
} }
} else { } else {
// it's a command // it's a command
container.LivenessProbe = helm.NewProbe(0, 0, 0, 0) container.LivenessProbe = p
container.LivenessProbe.Exec = &helm.Exec{ container.LivenessProbe.Exec = &helm.Exec{
Command: []string{ Command: []string{
"sh", "sh",
@@ -496,8 +497,7 @@ func prepareProbes(name string, s types.ServiceConfig, container *helm.Container
} }
// buildProtoProbe builds a probe from a url that can be http or tcp. // buildProtoProbe builds a probe from a url that can be http or tcp.
func buildProtoProbe(u *url.URL) *helm.Probe { func buildProtoProbe(probe *helm.Probe, u *url.URL) *helm.Probe {
probe := helm.NewProbe(0, 0, 0, 0)
port, err := strconv.Atoi(u.Port()) port, err := strconv.Atoi(u.Port())
if err != nil { if err != nil {
port = 80 port = 80
@@ -529,7 +529,8 @@ func buildCommandProbe(s types.ServiceConfig) *helm.Probe {
// Get the first element of the command from ServiceConfig // Get the first element of the command from ServiceConfig
first := s.HealthCheck.Test[0] first := s.HealthCheck.Test[0]
p := helm.NewProbe(0, 0, 0, 0)
p := helm.NewProbeFromService(&s)
switch first { switch first {
case "CMD", "CMD-SHELL": case "CMD", "CMD-SHELL":
// CMD or CMD-SHELL // CMD or CMD-SHELL

View File

@@ -1,18 +1,24 @@
package helm package helm
import (
"time"
"github.com/compose-spec/compose-go/types"
)
// Probe is a struct that can be used to create a Liveness or Readiness probe. // Probe is a struct that can be used to create a Liveness or Readiness probe.
type Probe struct { type Probe struct {
HttpGet *HttpGet `yaml:"httpGet,omitempty"` HttpGet *HttpGet `yaml:"httpGet,omitempty"`
Exec *Exec `yaml:"exec,omitempty"` Exec *Exec `yaml:"exec,omitempty"`
TCP *TCP `yaml:"tcp,omitempty"` TCP *TCP `yaml:"tcp,omitempty"`
Period int `yaml:"periodSeconds"` Period float64 `yaml:"periodSeconds"`
Success int `yaml:"successThreshold"` InitialDelay float64 `yaml:"initialDelaySeconds"`
Failure int `yaml:"failureThreshold"` Success uint64 `yaml:"successThreshold"`
InitialDelay int `yaml:"initialDelaySeconds"` Failure uint64 `yaml:"failureThreshold"`
} }
// Create a new Probe object that can be apply to HttpProbe or TCPProbe. // Create a new Probe object that can be apply to HttpProbe or TCPProbe.
func NewProbe(period, initialDelaySeconds, success, failure int) *Probe { func NewProbe(period, initialDelaySeconds float64, success, failure uint64) *Probe {
probe := &Probe{ probe := &Probe{
Period: period, Period: period,
Success: success, Success: success,
@@ -34,6 +40,53 @@ func NewProbe(period, initialDelaySeconds, success, failure int) *Probe {
return probe return probe
} }
// NewProbeWithDuration creates a new Probe object with the given duration from types.
func NewProbeWithDuration(period, initialDelaySeconds *types.Duration, success, failure *uint64) *Probe {
if period == nil {
d := types.Duration(0 * time.Second)
period = &d
}
if initialDelaySeconds == nil {
d := types.Duration(0 * time.Second)
initialDelaySeconds = &d
}
if success == nil {
s := uint64(0)
success = &s
}
if failure == nil {
f := uint64(0)
failure = &f
}
p, err := time.ParseDuration(period.String())
if err != nil {
p = time.Second * 10
}
i, err := time.ParseDuration(initialDelaySeconds.String())
if err != nil {
i = time.Second * 0
}
return NewProbe(p.Seconds(), i.Seconds(), *success, *failure)
}
// NewProbeFromService creates a new Probe object from a ServiceConfig.
func NewProbeFromService(s *types.ServiceConfig) *Probe {
if s == nil || s.HealthCheck == nil {
return NewProbe(0, 0, 0, 0)
}
return NewProbeWithDuration(s.HealthCheck.Interval, s.HealthCheck.StartPeriod, nil, s.HealthCheck.Retries)
}
// HttpGet is a Probe configuration to check http health. // HttpGet is a Probe configuration to check http health.
type HttpGet struct { type HttpGet struct {
Path string `yaml:"path"` Path string `yaml:"path"`