Move from bool to HealthCheckStatus

This commit is contained in:
Brendan Burns 2014-07-11 10:02:59 -07:00
parent 6312ffebcf
commit 1b4dfe7d14
4 changed files with 31 additions and 23 deletions

View File

@ -25,10 +25,16 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
) )
// HealthChecker is an abstract interface for container health checker. type HealthCheckStatus int
const (
CheckHealthy HealthCheckStatus = 0
CheckUnhealthy HealthCheckStatus = 1
CheckUnknown HealthCheckStatus = 2
)
type HealthChecker interface { type HealthChecker interface {
// IsHealthy checks if the container is healthy. HealthCheck(container api.Container) (HealthCheckStatus, error)
IsHealthy(container api.Container) (bool, error)
} }
type httpDoInterface interface { type httpDoInterface interface {
@ -51,14 +57,13 @@ type MuxHealthChecker struct {
checkers map[string]HealthChecker checkers map[string]HealthChecker
} }
// IsHealthy checks the health of the container by delegating to an appropriate HealthChecker according to container.LivenessProbe.Type. func (m *MuxHealthChecker) HealthCheck(container api.Container) (HealthCheckStatus, error) {
func (m *MuxHealthChecker) IsHealthy(container api.Container) (bool, error) {
checker, ok := m.checkers[container.LivenessProbe.Type] checker, ok := m.checkers[container.LivenessProbe.Type]
if !ok || checker == nil { if !ok || checker == nil {
glog.Warningf("Failed to find health checker for %s %s", container.Name, container.LivenessProbe.Type) glog.Warningf("Failed to find health checker for %s %s", container.Name, container.LivenessProbe.Type)
return true, nil return CheckUnknown, nil
} }
return checker.IsHealthy(container) return checker.HealthCheck(container)
} }
// HTTPHealthChecker is an implementation of HealthChecker which checks container health by sending HTTP Get requests. // HTTPHealthChecker is an implementation of HealthChecker which checks container health by sending HTTP Get requests.
@ -76,18 +81,17 @@ func (h *HTTPHealthChecker) findPort(container api.Container, portName string) i
return -1 return -1
} }
// IsHealthy checks if the container is healthy by trying sending HTTP Get requests to the container. func (h *HTTPHealthChecker) HealthCheck(container api.Container) (HealthCheckStatus, error) {
func (h *HTTPHealthChecker) IsHealthy(container api.Container) (bool, error) {
params := container.LivenessProbe.HTTPGet params := container.LivenessProbe.HTTPGet
if params == nil { if params == nil {
return true, fmt.Errorf("Error, no HTTP parameters specified: %v", container) return CheckUnknown, fmt.Errorf("Error, no HTTP parameters specified: %v", container)
} }
port := h.findPort(container, params.Port) port := h.findPort(container, params.Port)
if port == -1 { if port == -1 {
var err error var err error
port, err = strconv.ParseInt(params.Port, 10, 0) port, err = strconv.ParseInt(params.Port, 10, 0)
if err != nil { if err != nil {
return true, err return CheckUnknown, err
} }
} }
var host string var host string
@ -103,7 +107,11 @@ func (h *HTTPHealthChecker) IsHealthy(container api.Container) (bool, error) {
} }
if err != nil { if err != nil {
// At this point, if it fails, its either a policy (unlikely) or HTTP protocol (likely) error. // At this point, if it fails, its either a policy (unlikely) or HTTP protocol (likely) error.
return false, nil return CheckUnhealthy, nil
} }
return res.StatusCode == http.StatusOK, nil if res.StatusCode == http.StatusOK {
return CheckHealthy, nil
}
glog.V(1).Infof("Health check failed for %v, Response: %v", container, *res)
return CheckUnhealthy, nil
} }

View File

@ -55,8 +55,8 @@ func TestHttpHealth(t *testing.T) {
}, },
} }
ok, err := check.IsHealthy(container) ok, err := check.HealthCheck(container)
if !ok { if ok != CheckHealthy {
t.Error("Unexpected unhealthy") t.Error("Unexpected unhealthy")
} }
if err != nil { if err != nil {

View File

@ -732,7 +732,7 @@ func (kl *Kubelet) syncManifest(manifest *api.ContainerManifest, keepChannel cha
glog.V(1).Infof("health check errored: %v", err) glog.V(1).Infof("health check errored: %v", err)
continue continue
} }
if !healthy { if healthy != CheckHealthy {
glog.V(1).Infof("manifest %s container %s is unhealthy.", manifest.ID, container.Name) glog.V(1).Infof("manifest %s container %s is unhealthy.", manifest.ID, container.Name)
if err != nil { if err != nil {
glog.V(1).Infof("Failed to get container info %v, for %s", err, containerID) glog.V(1).Infof("Failed to get container info %v, for %s", err, containerID)
@ -989,16 +989,16 @@ func (kl *Kubelet) GetMachineStats() (*api.ContainerStats, error) {
return kl.statsFromContainerPath("/") return kl.statsFromContainerPath("/")
} }
func (kl *Kubelet) healthy(container api.Container, dockerContainer *docker.APIContainers) (bool, error) { func (kl *Kubelet) healthy(container api.Container, dockerContainer *docker.APIContainers) (HealthCheckStatus, error) {
// Give the container 60 seconds to start up. // Give the container 60 seconds to start up.
if container.LivenessProbe == nil { if container.LivenessProbe == nil {
return true, nil return CheckHealthy, nil
} }
if time.Now().Unix()-dockerContainer.Created < container.LivenessProbe.InitialDelaySeconds { if time.Now().Unix()-dockerContainer.Created < container.LivenessProbe.InitialDelaySeconds {
return true, nil return CheckHealthy, nil
} }
if kl.HealthChecker == nil { if kl.HealthChecker == nil {
return true, nil return CheckHealthy, nil
} }
return kl.HealthChecker.IsHealthy(container) return kl.HealthChecker.HealthCheck(container)
} }

View File

@ -424,8 +424,8 @@ func TestSyncManifestsDeletes(t *testing.T) {
type FalseHealthChecker struct{} type FalseHealthChecker struct{}
func (f *FalseHealthChecker) IsHealthy(container api.Container) (bool, error) { func (f *FalseHealthChecker) HealthCheck(container api.Container) (HealthCheckStatus, error) {
return false, nil return CheckUnhealthy, nil
} }
func TestSyncManifestsUnhealthy(t *testing.T) { func TestSyncManifestsUnhealthy(t *testing.T) {