-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add reload/leave http endpoints #2516
Changes from 5 commits
3ad50a5
7bd6e22
c88738f
f47bbc5
a60b22a
d27b3f0
b179d28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,6 +39,18 @@ func (s *HTTPServer) AgentSelf(resp http.ResponseWriter, req *http.Request) (int | |
}, nil | ||
} | ||
|
||
func (s *HTTPServer) AgentReload(resp http.ResponseWriter, req *http.Request) (interface{}, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's make these new ones require a PUT otherwise give a 405. Might as well start these off in a better spot :-) |
||
if req.Method != "PUT" { | ||
resp.WriteHeader(http.StatusMethodNotAllowed) | ||
return nil, nil | ||
} | ||
|
||
errCh := make(chan error, 0) | ||
s.agent.reloadCh <- errCh | ||
|
||
return nil, <-errCh | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should wait on the shutdown channel too, and return some kind of error. |
||
} | ||
|
||
func (s *HTTPServer) AgentServices(resp http.ResponseWriter, req *http.Request) (interface{}, error) { | ||
services := s.agent.state.Services() | ||
return services, nil | ||
|
@@ -80,6 +92,18 @@ func (s *HTTPServer) AgentJoin(resp http.ResponseWriter, req *http.Request) (int | |
} | ||
} | ||
|
||
func (s *HTTPServer) AgentLeave(resp http.ResponseWriter, req *http.Request) (interface{}, error) { | ||
if req.Method != "PUT" { | ||
resp.WriteHeader(http.StatusMethodNotAllowed) | ||
return nil, nil | ||
} | ||
|
||
if err := s.agent.Leave(); err != nil { | ||
return nil, err | ||
} | ||
return nil, s.agent.Shutdown() | ||
} | ||
|
||
func (s *HTTPServer) AgentForceLeave(resp http.ResponseWriter, req *http.Request) (interface{}, error) { | ||
addr := strings.TrimPrefix(req.URL.Path, "/v1/agent/force-leave/") | ||
return nil, s.agent.ForceLeave(addr) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ import ( | |
"github.com/hashicorp/consul/testutil" | ||
"github.com/hashicorp/consul/types" | ||
"github.com/hashicorp/serf/serf" | ||
"github.com/mitchellh/cli" | ||
) | ||
|
||
func TestHTTPAgentServices(t *testing.T) { | ||
|
@@ -119,6 +120,81 @@ func TestHTTPAgentSelf(t *testing.T) { | |
} | ||
} | ||
|
||
func TestHTTPAgentReload(t *testing.T) { | ||
conf := nextConfig() | ||
tmpDir, err := ioutil.TempDir("", "consul") | ||
if err != nil { | ||
t.Fatalf("err: %s", err) | ||
} | ||
defer os.RemoveAll(tmpDir) | ||
|
||
// Write initial config, to be reloaded later | ||
tmpFile, err := ioutil.TempFile(tmpDir, "config") | ||
if err != nil { | ||
t.Fatalf("err: %s", err) | ||
} | ||
_, err = tmpFile.WriteString(`{"service":{"name":"redis"}}`) | ||
if err != nil { | ||
t.Fatalf("err: %s", err) | ||
} | ||
tmpFile.Close() | ||
|
||
doneCh := make(chan struct{}) | ||
shutdownCh := make(chan struct{}) | ||
|
||
defer func() { | ||
close(shutdownCh) | ||
<-doneCh | ||
}() | ||
|
||
cmd := &Command{ | ||
ShutdownCh: shutdownCh, | ||
Ui: new(cli.MockUi), | ||
} | ||
|
||
args := []string{ | ||
"-server", | ||
"-data-dir", tmpDir, | ||
"-http-port", fmt.Sprintf("%d", conf.Ports.HTTP), | ||
"-config-file", tmpFile.Name(), | ||
} | ||
|
||
go func() { | ||
cmd.Run(args) | ||
close(doneCh) | ||
}() | ||
|
||
testutil.WaitForResult(func() (bool, error) { | ||
return len(cmd.httpServers) == 1, nil | ||
}, func(err error) { | ||
t.Fatalf("should have an http server") | ||
}) | ||
|
||
if _, ok := cmd.agent.state.services["redis"]; !ok { | ||
t.Fatalf("missing redis service") | ||
} | ||
|
||
err = ioutil.WriteFile(tmpFile.Name(), []byte(`{"service":{"name":"redis-reloaded"}}`), 0644) | ||
if err != nil { | ||
t.Fatalf("err: %v", err) | ||
} | ||
|
||
srv := cmd.httpServers[0] | ||
req, err := http.NewRequest("PUT", "/v1/agent/reload", nil) | ||
if err != nil { | ||
t.Fatalf("err: %v", err) | ||
} | ||
|
||
_, err = srv.AgentReload(nil, req) | ||
if err != nil { | ||
t.Fatalf("Err: %v", err) | ||
} | ||
|
||
if _, ok := cmd.agent.state.services["redis-reloaded"]; !ok { | ||
t.Fatalf("missing redis-reloaded service") | ||
} | ||
} | ||
|
||
func TestHTTPAgentMembers(t *testing.T) { | ||
dir, srv := makeHTTPServer(t) | ||
defer os.RemoveAll(dir) | ||
|
@@ -239,6 +315,49 @@ func TestHTTPAgentJoin_WAN(t *testing.T) { | |
}) | ||
} | ||
|
||
func TestHTTPAgentLeave(t *testing.T) { | ||
dir, srv := makeHTTPServer(t) | ||
defer os.RemoveAll(dir) | ||
defer srv.Shutdown() | ||
defer srv.agent.Shutdown() | ||
|
||
dir2, srv2 := makeHTTPServerWithConfig(t, func(c *Config) { | ||
c.Server = false | ||
c.Bootstrap = false | ||
}) | ||
defer os.RemoveAll(dir2) | ||
defer srv2.Shutdown() | ||
|
||
// Join first | ||
addr := fmt.Sprintf("127.0.0.1:%d", srv2.agent.config.Ports.SerfLan) | ||
_, err := srv.agent.JoinLAN([]string{addr}) | ||
if err != nil { | ||
t.Fatalf("err: %v", err) | ||
} | ||
|
||
// Graceful leave now | ||
req, err := http.NewRequest("PUT", "/v1/agent/leave", nil) | ||
if err != nil { | ||
t.Fatalf("err: %v", err) | ||
} | ||
|
||
obj, err := srv2.AgentLeave(nil, req) | ||
if err != nil { | ||
t.Fatalf("Err: %v", err) | ||
} | ||
if obj != nil { | ||
t.Fatalf("Err: %v", obj) | ||
} | ||
|
||
testutil.WaitForResult(func() (bool, error) { | ||
m := srv.agent.LANMembers() | ||
success := m[1].Status == serf.StatusLeft | ||
return success, errors.New(m[1].Status.String()) | ||
}, func(err error) { | ||
t.Fatalf("member status is %v, should be left", err) | ||
}) | ||
} | ||
|
||
func TestHTTPAgentForceLeave(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should have a reload test as well. |
||
dir, srv := makeHTTPServer(t) | ||
defer os.RemoveAll(dir) | ||
|
@@ -1030,7 +1149,6 @@ func TestHTTPAgent_Monitor(t *testing.T) { | |
logger := io.MultiWriter(os.Stdout, &expectedLogs, logWriter) | ||
|
||
dir, srv := makeHTTPServerWithConfigLog(t, nil, logger, logWriter) | ||
srv.agent.logWriter = logWriter | ||
defer os.RemoveAll(dir) | ||
defer srv.Shutdown() | ||
defer srv.agent.Shutdown() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can drop this now, right?