agent: support passing ?reason= for custom notes field values on maintenance checks

This commit is contained in:
Ryan Uber 2015-01-21 12:21:57 -08:00
parent 5694ac6821
commit f00b5b542e
4 changed files with 78 additions and 16 deletions

View File

@ -1027,7 +1027,7 @@ func serviceMaintCheckID(serviceID string) string {
// EnableServiceMaintenance will register a false health check against the given // EnableServiceMaintenance will register a false health check against the given
// service ID with critical status. This will exclude the service from queries. // service ID with critical status. This will exclude the service from queries.
func (a *Agent) EnableServiceMaintenance(serviceID string) error { func (a *Agent) EnableServiceMaintenance(serviceID, reason string) error {
service, ok := a.state.Services()[serviceID] service, ok := a.state.Services()[serviceID]
if !ok { if !ok {
return fmt.Errorf("No service registered with ID %q", serviceID) return fmt.Errorf("No service registered with ID %q", serviceID)
@ -1039,12 +1039,17 @@ func (a *Agent) EnableServiceMaintenance(serviceID string) error {
return nil return nil
} }
// Use default notes if no reason provided
if reason == "" {
reason = "Maintenance mode is enabled for this service"
}
// Create and register the critical health check // Create and register the critical health check
check := &structs.HealthCheck{ check := &structs.HealthCheck{
Node: a.config.NodeName, Node: a.config.NodeName,
CheckID: checkID, CheckID: checkID,
Name: "Service Maintenance Mode", Name: "Service Maintenance Mode",
Notes: "Maintenance mode is enabled for this service", Notes: reason,
ServiceID: service.ID, ServiceID: service.ID,
ServiceName: service.Service, ServiceName: service.Service,
Status: structs.HealthCritical, Status: structs.HealthCritical,
@ -1076,18 +1081,23 @@ func (a *Agent) DisableServiceMaintenance(serviceID string) error {
} }
// EnableNodeMaintenance places a node into maintenance mode. // EnableNodeMaintenance places a node into maintenance mode.
func (a *Agent) EnableNodeMaintenance() { func (a *Agent) EnableNodeMaintenance(reason string) {
// Ensure node maintenance is not already enabled // Ensure node maintenance is not already enabled
if _, ok := a.state.Checks()[nodeMaintCheckID]; ok { if _, ok := a.state.Checks()[nodeMaintCheckID]; ok {
return return
} }
// Use a default notes value
if reason == "" {
reason = "Maintenance mode is enabled for this node"
}
// Create and register the node maintenance check // Create and register the node maintenance check
check := &structs.HealthCheck{ check := &structs.HealthCheck{
Node: a.config.NodeName, Node: a.config.NodeName,
CheckID: nodeMaintCheckID, CheckID: nodeMaintCheckID,
Name: "Node Maintenance Mode", Name: "Node Maintenance Mode",
Notes: "Maintenance mode is enabled for this node", Notes: reason,
Status: structs.HealthCritical, Status: structs.HealthCritical,
} }
a.AddCheck(check, nil, true) a.AddCheck(check, nil, true)

View File

@ -220,7 +220,8 @@ func (s *HTTPServer) AgentServiceMaintenance(resp http.ResponseWriter, req *http
} }
if enable { if enable {
if err = s.agent.EnableServiceMaintenance(serviceID); err != nil { reason := params.Get("reason")
if err = s.agent.EnableServiceMaintenance(serviceID, reason); err != nil {
resp.WriteHeader(404) resp.WriteHeader(404)
resp.Write([]byte(err.Error())) resp.Write([]byte(err.Error()))
} }
@ -257,7 +258,7 @@ func (s *HTTPServer) AgentNodeMaintenance(resp http.ResponseWriter, req *http.Re
} }
if enable { if enable {
s.agent.EnableNodeMaintenance() s.agent.EnableNodeMaintenance(params.Get("reason"))
} else { } else {
s.agent.DisableNodeMaintenance() s.agent.DisableNodeMaintenance()
} }

View File

@ -566,7 +566,7 @@ func TestHTTPAgent_EnableServiceMaintenance(t *testing.T) {
} }
// Force the service into maintenance mode // Force the service into maintenance mode
req, _ := http.NewRequest("PUT", "/v1/agent/service/maintenance/test?enable=true", nil) req, _ := http.NewRequest("PUT", "/v1/agent/service/maintenance/test?enable=true&reason=broken", nil)
resp := httptest.NewRecorder() resp := httptest.NewRecorder()
if _, err := srv.AgentServiceMaintenance(resp, req); err != nil { if _, err := srv.AgentServiceMaintenance(resp, req); err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
@ -577,9 +577,15 @@ func TestHTTPAgent_EnableServiceMaintenance(t *testing.T) {
// Ensure the maintenance check was registered // Ensure the maintenance check was registered
checkID := serviceMaintCheckID("test") checkID := serviceMaintCheckID("test")
if _, ok := srv.agent.state.Checks()[checkID]; !ok { check, ok := srv.agent.state.Checks()[checkID]
if !ok {
t.Fatalf("should have registered maintenance check") t.Fatalf("should have registered maintenance check")
} }
// Ensure the reason was set in notes
if check.Notes != "broken" {
t.Fatalf("bad: %#v", check)
}
} }
func TestHTTPAgent_DisableServiceMaintenance(t *testing.T) { func TestHTTPAgent_DisableServiceMaintenance(t *testing.T) {
@ -598,7 +604,7 @@ func TestHTTPAgent_DisableServiceMaintenance(t *testing.T) {
} }
// Force the service into maintenance mode // Force the service into maintenance mode
if err := srv.agent.EnableServiceMaintenance("test"); err != nil { if err := srv.agent.EnableServiceMaintenance("test", ""); err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
@ -653,7 +659,8 @@ func TestHTTPAgent_EnableNodeMaintenance(t *testing.T) {
defer srv.agent.Shutdown() defer srv.agent.Shutdown()
// Force the node into maintenance mode // Force the node into maintenance mode
req, _ := http.NewRequest("PUT", "/v1/agent/self/maintenance?enable=true", nil) req, _ := http.NewRequest(
"PUT", "/v1/agent/self/maintenance?enable=true&reason=broken", nil)
resp := httptest.NewRecorder() resp := httptest.NewRecorder()
if _, err := srv.AgentNodeMaintenance(resp, req); err != nil { if _, err := srv.AgentNodeMaintenance(resp, req); err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
@ -663,9 +670,15 @@ func TestHTTPAgent_EnableNodeMaintenance(t *testing.T) {
} }
// Ensure the maintenance check was registered // Ensure the maintenance check was registered
if _, ok := srv.agent.state.Checks()[nodeMaintCheckID]; !ok { check, ok := srv.agent.state.Checks()[nodeMaintCheckID]
if !ok {
t.Fatalf("should have registered maintenance check") t.Fatalf("should have registered maintenance check")
} }
// Ensure the reason was set in notes
if check.Notes != "broken" {
t.Fatalf("bad: %#v", check)
}
} }
func TestHTTPAgent_DisableNodeMaintenance(t *testing.T) { func TestHTTPAgent_DisableNodeMaintenance(t *testing.T) {
@ -675,7 +688,7 @@ func TestHTTPAgent_DisableNodeMaintenance(t *testing.T) {
defer srv.agent.Shutdown() defer srv.agent.Shutdown()
// Force the node into maintenance mode // Force the node into maintenance mode
srv.agent.EnableNodeMaintenance() srv.agent.EnableNodeMaintenance("")
// Leave maintenance mode // Leave maintenance mode
req, _ := http.NewRequest("PUT", "/v1/agent/self/maintenance?enable=false", nil) req, _ := http.NewRequest("PUT", "/v1/agent/self/maintenance?enable=false", nil)

View File

@ -916,16 +916,22 @@ func TestAgent_ServiceMaintenanceMode(t *testing.T) {
} }
// Enter maintenance mode for the service // Enter maintenance mode for the service
if err := agent.EnableServiceMaintenance("redis"); err != nil { if err := agent.EnableServiceMaintenance("redis", "broken"); err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
// Make sure the critical health check was added // Make sure the critical health check was added
checkID := serviceMaintCheckID("redis") checkID := serviceMaintCheckID("redis")
if _, ok := agent.state.Checks()[checkID]; !ok { check, ok := agent.state.Checks()[checkID]
if !ok {
t.Fatalf("should have registered critical maintenance check") t.Fatalf("should have registered critical maintenance check")
} }
// Ensure the reason was set in notes
if check.Notes != "broken" {
t.Fatalf("bad: %#v", check)
}
// Leave maintenance mode // Leave maintenance mode
if err := agent.DisableServiceMaintenance("redis"); err != nil { if err := agent.DisableServiceMaintenance("redis"); err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
@ -935,6 +941,20 @@ func TestAgent_ServiceMaintenanceMode(t *testing.T) {
if _, ok := agent.state.Checks()[checkID]; ok { if _, ok := agent.state.Checks()[checkID]; ok {
t.Fatalf("should have deregistered maintenance check") t.Fatalf("should have deregistered maintenance check")
} }
// Enter service maintenance mode without providing a reason
if err := agent.EnableServiceMaintenance("redis", ""); err != nil {
t.Fatalf("err: %s", err)
}
// Ensure the check was registered with the default notes
check, ok = agent.state.Checks()[checkID]
if !ok {
t.Fatalf("should have registered critical check")
}
if check.Notes == "" {
t.Fatalf("bad: %#v", check)
}
} }
func TestAgent_NodeMaintenanceMode(t *testing.T) { func TestAgent_NodeMaintenanceMode(t *testing.T) {
@ -944,13 +964,19 @@ func TestAgent_NodeMaintenanceMode(t *testing.T) {
defer agent.Shutdown() defer agent.Shutdown()
// Enter maintenance mode for the node // Enter maintenance mode for the node
agent.EnableNodeMaintenance() agent.EnableNodeMaintenance("broken")
// Make sure the critical health check was added // Make sure the critical health check was added
if _, ok := agent.state.Checks()[nodeMaintCheckID]; !ok { check, ok := agent.state.Checks()[nodeMaintCheckID]
if !ok {
t.Fatalf("should have registered critical node check") t.Fatalf("should have registered critical node check")
} }
// Ensure the reason was set in notes
if check.Notes != "broken" {
t.Fatalf("bad: %#v", check)
}
// Leave maintenance mode // Leave maintenance mode
agent.DisableNodeMaintenance() agent.DisableNodeMaintenance()
@ -958,4 +984,16 @@ func TestAgent_NodeMaintenanceMode(t *testing.T) {
if _, ok := agent.state.Checks()[nodeMaintCheckID]; ok { if _, ok := agent.state.Checks()[nodeMaintCheckID]; ok {
t.Fatalf("should have deregistered critical node check") t.Fatalf("should have deregistered critical node check")
} }
// Enter maintenance mode without passing a reason
agent.EnableNodeMaintenance("")
// Make sure the check was registered with the default note
check, ok = agent.state.Checks()[nodeMaintCheckID]
if !ok {
t.Fatalf("should have registered critical node check")
}
if check.Notes == "" {
t.Fatalf("bad: %#v", check)
}
} }