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

View File

@ -220,7 +220,8 @@ func (s *HTTPServer) AgentServiceMaintenance(resp http.ResponseWriter, req *http
}
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.Write([]byte(err.Error()))
}
@ -257,7 +258,7 @@ func (s *HTTPServer) AgentNodeMaintenance(resp http.ResponseWriter, req *http.Re
}
if enable {
s.agent.EnableNodeMaintenance()
s.agent.EnableNodeMaintenance(params.Get("reason"))
} else {
s.agent.DisableNodeMaintenance()
}

View File

@ -566,7 +566,7 @@ func TestHTTPAgent_EnableServiceMaintenance(t *testing.T) {
}
// 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()
if _, err := srv.AgentServiceMaintenance(resp, req); err != nil {
t.Fatalf("err: %s", err)
@ -577,9 +577,15 @@ func TestHTTPAgent_EnableServiceMaintenance(t *testing.T) {
// Ensure the maintenance check was registered
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")
}
// Ensure the reason was set in notes
if check.Notes != "broken" {
t.Fatalf("bad: %#v", check)
}
}
func TestHTTPAgent_DisableServiceMaintenance(t *testing.T) {
@ -598,7 +604,7 @@ func TestHTTPAgent_DisableServiceMaintenance(t *testing.T) {
}
// 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)
}
@ -653,7 +659,8 @@ func TestHTTPAgent_EnableNodeMaintenance(t *testing.T) {
defer srv.agent.Shutdown()
// 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()
if _, err := srv.AgentNodeMaintenance(resp, req); err != nil {
t.Fatalf("err: %s", err)
@ -663,9 +670,15 @@ func TestHTTPAgent_EnableNodeMaintenance(t *testing.T) {
}
// 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")
}
// Ensure the reason was set in notes
if check.Notes != "broken" {
t.Fatalf("bad: %#v", check)
}
}
func TestHTTPAgent_DisableNodeMaintenance(t *testing.T) {
@ -675,7 +688,7 @@ func TestHTTPAgent_DisableNodeMaintenance(t *testing.T) {
defer srv.agent.Shutdown()
// Force the node into maintenance mode
srv.agent.EnableNodeMaintenance()
srv.agent.EnableNodeMaintenance("")
// Leave maintenance mode
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
if err := agent.EnableServiceMaintenance("redis"); err != nil {
if err := agent.EnableServiceMaintenance("redis", "broken"); err != nil {
t.Fatalf("err: %s", err)
}
// Make sure the critical health check was added
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")
}
// Ensure the reason was set in notes
if check.Notes != "broken" {
t.Fatalf("bad: %#v", check)
}
// Leave maintenance mode
if err := agent.DisableServiceMaintenance("redis"); err != nil {
t.Fatalf("err: %s", err)
@ -935,6 +941,20 @@ func TestAgent_ServiceMaintenanceMode(t *testing.T) {
if _, ok := agent.state.Checks()[checkID]; ok {
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) {
@ -944,13 +964,19 @@ func TestAgent_NodeMaintenanceMode(t *testing.T) {
defer agent.Shutdown()
// Enter maintenance mode for the node
agent.EnableNodeMaintenance()
agent.EnableNodeMaintenance("broken")
// 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")
}
// Ensure the reason was set in notes
if check.Notes != "broken" {
t.Fatalf("bad: %#v", check)
}
// Leave maintenance mode
agent.DisableNodeMaintenance()
@ -958,4 +984,16 @@ func TestAgent_NodeMaintenanceMode(t *testing.T) {
if _, ok := agent.state.Checks()[nodeMaintCheckID]; ok {
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)
}
}