agent: first pass at service maintenance mode

This commit is contained in:
Ryan Uber 2015-01-15 00:16:34 -08:00
parent 559af1485c
commit 4f4eb204f6
3 changed files with 104 additions and 0 deletions

View File

@ -29,6 +29,9 @@ const (
"If Consul was not shut down properly, the socket file may " +
"be left behind. If the path looks correct, remove the file " +
"and try again."
// The ID of the faux health check for maintenance mode
maintCheckID = "_maintenance_"
)
/*
@ -995,3 +998,66 @@ func (a *Agent) unloadChecks() error {
return nil
}
func (a *Agent) EnableServiceMaintenance(serviceID string) error {
var service *structs.NodeService
for _, svc := range a.state.Services() {
if svc.ID == serviceID {
service = svc
}
}
// Ensure the service exists
if service == nil {
return fmt.Errorf("No service registered with ID %q", serviceID)
}
// Ensure maintenance mode is not already enabled
for _, check := range a.state.Checks() {
if check.CheckID == maintCheckID {
return fmt.Errorf("Maintenance mode already enabled for service %q", serviceID)
}
}
// Create and register the critical health check
check := &structs.HealthCheck{
Node: a.config.NodeName,
CheckID: maintCheckID,
Name: "Service Maintenance Mode",
Notes: "Maintenance mode is enabled for this service",
ServiceID: service.ID,
ServiceName: service.Service,
Status: structs.HealthCritical,
}
a.state.AddCheck(check)
return nil
}
func (a *Agent) DisableServiceMaintenance(serviceID string) error {
var service *structs.NodeService
for _, svc := range a.state.Services() {
if svc.ID == serviceID {
service = svc
}
}
// Ensure the service exists
if service == nil {
return fmt.Errorf("No service registered with ID %q", serviceID)
}
// Ensure maintenance mode is enabled
for _, check := range a.state.Checks() {
if check.CheckID == maintCheckID {
goto DEREGISTER
}
}
return fmt.Errorf("Maintenance mode not enabled for service %q", serviceID)
DEREGISTER:
// Deregister the maintenance check
a.state.RemoveCheck(maintCheckID)
return nil
}

View File

@ -176,3 +176,40 @@ func (s *HTTPServer) AgentDeregisterService(resp http.ResponseWriter, req *http.
serviceID := strings.TrimPrefix(req.URL.Path, "/v1/agent/service/deregister/")
return nil, s.agent.RemoveService(serviceID, true)
}
func (s *HTTPServer) AgentServiceMaintenance(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
// Ensure we have a service ID
serviceID := strings.TrimPrefix(req.URL.Path, "/v1/agent/service/maintenance/")
if serviceID == "" {
resp.WriteHeader(400)
resp.Write([]byte("Missing service ID"))
return nil, nil
}
// Ensure we have some action
params := req.URL.Query()
if _, ok := params["enable"]; !ok {
resp.WriteHeader(400)
resp.Write([]byte("Missing value for enable"))
return nil, nil
}
var enable bool
raw := params.Get("enable")
switch raw {
case "true":
enable = true
case "false":
enable = false
default:
resp.WriteHeader(400)
resp.Write([]byte(fmt.Sprintf("Invalid value for enable: %q", raw)))
return nil, nil
}
if enable {
return nil, s.agent.EnableServiceMaintenance(serviceID)
} else {
return nil, s.agent.DisableServiceMaintenance(serviceID)
}
}

View File

@ -195,6 +195,7 @@ func (s *HTTPServer) registerHandlers(enableDebug bool) {
s.mux.HandleFunc("/v1/agent/service/register", s.wrap(s.AgentRegisterService))
s.mux.HandleFunc("/v1/agent/service/deregister/", s.wrap(s.AgentDeregisterService))
s.mux.HandleFunc("/v1/agent/service/maintenance/", s.wrap(s.AgentServiceMaintenance))
s.mux.HandleFunc("/v1/event/fire/", s.wrap(s.EventFire))
s.mux.HandleFunc("/v1/event/list", s.wrap(s.EventList))