From 114b38b8a839fb6616e8dad5c1340183094eea20 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Thu, 24 Sep 2015 20:39:03 -0700 Subject: [PATCH] agent: add HTTP endpoint for querying/modifying the server list --- command/agent/agent_endpoint.go | 38 +++++++++++++++++++++ command/agent/agent_endpoint_test.go | 51 ++++++++++++++++++++++++++++ command/agent/http.go | 1 + 3 files changed, 90 insertions(+) diff --git a/command/agent/agent_endpoint.go b/command/agent/agent_endpoint.go index 73e73e799..b2ca09599 100644 --- a/command/agent/agent_endpoint.go +++ b/command/agent/agent_endpoint.go @@ -119,6 +119,44 @@ func (s *HTTPServer) AgentForceLeaveRequest(resp http.ResponseWriter, req *http. return nil, err } +func (s *HTTPServer) AgentServersRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) { + switch req.Method { + case "PUT", "POST": + return s.updateServers(resp, req) + case "GET": + return s.listServers(resp, req) + default: + return nil, CodedError(405, ErrInvalidMethod) + } +} + +func (s *HTTPServer) listServers(resp http.ResponseWriter, req *http.Request) (interface{}, error) { + client := s.agent.Client() + if client == nil { + return nil, CodedError(501, ErrInvalidMethod) + } + + // Get the current list of servers + return client.Servers(), nil +} + +func (s *HTTPServer) updateServers(resp http.ResponseWriter, req *http.Request) (interface{}, error) { + client := s.agent.Client() + if client == nil { + return nil, CodedError(501, ErrInvalidMethod) + } + + // Get the servers from the request + servers := req.URL.Query()["address"] + if len(servers) == 0 { + return nil, CodedError(400, "missing server address") + } + + // Set the servers list into the client + client.SetServers(servers) + return nil, nil +} + type agentSelf struct { Config *Config `json:"config"` Member Member `json:"member,omitempty"` diff --git a/command/agent/agent_endpoint_test.go b/command/agent/agent_endpoint_test.go index 3b0ff17c4..0aed0508a 100644 --- a/command/agent/agent_endpoint_test.go +++ b/command/agent/agent_endpoint_test.go @@ -4,6 +4,7 @@ import ( "fmt" "net/http" "net/http/httptest" + "strings" "testing" ) @@ -103,3 +104,53 @@ func TestHTTP_AgentForceLeave(t *testing.T) { } }) } + +func TestHTTP_AgentSetServers(t *testing.T) { + httpTest(t, nil, func(s *TestServer) { + // Create the request + req, err := http.NewRequest("PUT", "/v1/agent/servers", nil) + if err != nil { + t.Fatalf("err: %s", err) + } + + // Send the request + respW := httptest.NewRecorder() + _, err = s.Server.AgentServersRequest(respW, req) + if err == nil || !strings.Contains(err.Error(), "missing server address") { + t.Fatalf("expected missing servers error, got: %#v", err) + } + + // Create a valid request + req, err = http.NewRequest("PUT", "/v1/agent/servers?address=foo&address=bar", nil) + if err != nil { + t.Fatalf("err: %s", err) + } + + // Send the request + respW = httptest.NewRecorder() + _, err = s.Server.AgentServersRequest(respW, req) + if err != nil { + t.Fatalf("err: %s", err) + } + + // Retrieve the servers again + req, err = http.NewRequest("GET", "/v1/agent/servers", nil) + if err != nil { + t.Fatalf("err: %s", err) + } + respW = httptest.NewRecorder() + + // Make the request and check the result + out, err := s.Server.AgentServersRequest(respW, req) + if err != nil { + t.Fatalf("err: %s", err) + } + servers := out.([]string) + if n := len(servers); n != 2 { + t.Fatalf("expected 2 servers, got: %d", n) + } + if servers[0] != "foo" || servers[1] != "bar" { + t.Fatalf("bad servers result: %v", servers) + } + }) +} diff --git a/command/agent/http.go b/command/agent/http.go index 8ecd789f8..ec306d00b 100644 --- a/command/agent/http.go +++ b/command/agent/http.go @@ -107,6 +107,7 @@ func (s *HTTPServer) registerHandlers(enableDebug bool) { s.mux.HandleFunc("/v1/agent/join", s.wrap(s.AgentJoinRequest)) s.mux.HandleFunc("/v1/agent/members", s.wrap(s.AgentMembersRequest)) s.mux.HandleFunc("/v1/agent/force-leave", s.wrap(s.AgentForceLeaveRequest)) + s.mux.HandleFunc("/v1/agent/servers", s.wrap(s.AgentServersRequest)) s.mux.HandleFunc("/v1/status/leader", s.wrap(s.StatusLeaderRequest)) s.mux.HandleFunc("/v1/status/peers", s.wrap(s.StatusPeersRequest))