diff --git a/cmd/ecs_credential_provider.go b/cmd/ecs_credential_provider.go index f8d933b..8abff6a 100644 --- a/cmd/ecs_credential_provider.go +++ b/cmd/ecs_credential_provider.go @@ -51,6 +51,7 @@ func runEcsMetadata(cmd *cobra.Command, args []string) error { listenAddr := fmt.Sprintf("%s:%d", ipaddress, ecsProviderListenPort) router := mux.NewRouter() + router.HandleFunc("/healthcheck", handlers.HealthcheckHandler) router.HandleFunc("/ecs/{role:.*}", handlers.MetaDataServiceMiddleware(handlers.ECSMetadataServiceCredentialsHandler)) router.HandleFunc("/{path:.*}", handlers.MetaDataServiceMiddleware(handlers.CustomHandler)) diff --git a/cmd/metadata.go b/cmd/metadata.go index 81770e1..d853349 100644 --- a/cmd/metadata.go +++ b/cmd/metadata.go @@ -65,6 +65,7 @@ func runMetadata(cmd *cobra.Command, args []string) error { listenAddr := fmt.Sprintf("%s:%d", ipaddress, metadataListenPort) router := mux.NewRouter() + router.HandleFunc("/healthcheck", handlers.HealthcheckHandler) router.HandleFunc("/{version}/", handlers.MetaDataServiceMiddleware(handlers.BaseVersionHandler)) router.HandleFunc("/{version}/api/token", handlers.MetaDataServiceMiddleware(handlers.TokenHandler)).Methods("PUT") router.HandleFunc("/{version}/meta-data", handlers.MetaDataServiceMiddleware(handlers.BaseHandler)) diff --git a/handlers/healthcheckHandler.go b/handlers/healthcheckHandler.go new file mode 100644 index 0000000..65b77ef --- /dev/null +++ b/handlers/healthcheckHandler.go @@ -0,0 +1,34 @@ +package handlers + +import ( + "encoding/json" + "net/http" + + "github.com/netflix/weep/health" + log "github.com/sirupsen/logrus" +) + +type healthcheckResponse struct { + Status int `json:"status"` + Message string `json:"message"` +} + +func HealthcheckHandler(w http.ResponseWriter, r *http.Request) { + healthy, reason := health.WeepStatus.Get() + var status int + if healthy { + status = http.StatusOK + } else { + status = http.StatusInternalServerError + } + resp := healthcheckResponse{ + Status: status, + Message: reason, + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(status) + err := json.NewEncoder(w).Encode(resp) + if err != nil { + log.Errorf("error writing healthcheck response: %v", err) + } +} diff --git a/health/health.go b/health/health.go new file mode 100644 index 0000000..46ec337 --- /dev/null +++ b/health/health.go @@ -0,0 +1,38 @@ +package health + +import "sync" + +var WeepStatus status + +type status struct { + sync.RWMutex + healthy bool + reason string +} + +func init() { + WeepStatus = status{ + healthy: true, + reason: "healthy", + } +} + +func (s *status) Get() (bool, string) { + s.RLock() + defer s.RUnlock() + return s.healthy, s.reason +} + +func (s *status) SetUnhealthy(reason string) { + s.Lock() + defer s.Unlock() + s.healthy = false + s.reason = reason +} + +func (s *status) SetHealthy() { + s.Lock() + defer s.Unlock() + s.healthy = true + s.reason = "healthy" +}