mirror of https://github.com/status-im/consul.git
agent: Adding nodes UI endpoint
This commit is contained in:
parent
7098807583
commit
fbce850317
|
@ -102,7 +102,11 @@ func (s *HTTPServer) registerHandlers(enableDebug bool) {
|
|||
|
||||
// Enable the UI + special endpoints
|
||||
if s.uiDir != "" {
|
||||
// Static file serving done from /ui/
|
||||
s.mux.Handle("/ui/", http.StripPrefix("/ui/", http.FileServer(http.Dir(s.uiDir))))
|
||||
|
||||
// API's are under /internal/ui/ to avoid conflict
|
||||
s.mux.HandleFunc("/v1/internal/ui/nodes/", s.wrap(s.UINodes))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,48 @@
|
|||
package agent
|
||||
|
||||
import ()
|
||||
import (
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// UINodes is used to list the nodes in a given datacenter. We return a
|
||||
// UINodeList which provides overview information for all the nodes
|
||||
func (s *HTTPServer) UINodes(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
// Verify we have some DC, or use the default
|
||||
dc := strings.TrimPrefix(req.URL.Path, "/v1/internal/ui/nodes/")
|
||||
if dc == "" {
|
||||
dc = s.agent.config.Datacenter
|
||||
}
|
||||
|
||||
// Try to ge ta node dump
|
||||
var dump structs.NodeDump
|
||||
if err := s.getNodeDump(resp, dc, &dump); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dump, nil
|
||||
}
|
||||
|
||||
// getNodeDump is used to get a dump of all node data. We make a best effort by
|
||||
// reading stale data in the case of an availability outage.
|
||||
func (s *HTTPServer) getNodeDump(resp http.ResponseWriter, dc string, dump *structs.NodeDump) error {
|
||||
args := structs.DCSpecificRequest{Datacenter: dc}
|
||||
var out structs.IndexedNodeDump
|
||||
defer setMeta(resp, &out.QueryMeta)
|
||||
|
||||
START:
|
||||
if err := s.agent.RPC("Internal.NodeDump", &args, &out); err != nil {
|
||||
// Retry the request allowing stale data if no leader. The UI should continue
|
||||
// to function even during an outage
|
||||
if strings.Contains(err.Error(), structs.ErrNoLeader.Error()) && !args.AllowStale {
|
||||
args.AllowStale = true
|
||||
goto START
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Set the result
|
||||
*dump = out.Dump
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package agent
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
@ -9,6 +10,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestUiIndex(t *testing.T) {
|
||||
|
@ -28,13 +30,17 @@ func TestUiIndex(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
req.URL.Scheme = "http"
|
||||
req.URL.Host = srv.listener.Addr().String()
|
||||
|
||||
// Make the request
|
||||
resp := httptest.NewRecorder()
|
||||
srv.UiIndex(resp, req)
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
// Verify teh response
|
||||
if resp.Code != 200 {
|
||||
if resp.StatusCode != 200 {
|
||||
t.Fatalf("bad: %v", resp)
|
||||
}
|
||||
|
||||
|
@ -45,3 +51,31 @@ func TestUiIndex(t *testing.T) {
|
|||
t.Fatalf("bad: %s", out.Bytes())
|
||||
}
|
||||
}
|
||||
|
||||
func TestUiNodes(t *testing.T) {
|
||||
dir, srv := makeHTTPServer(t)
|
||||
defer os.RemoveAll(dir)
|
||||
defer srv.Shutdown()
|
||||
defer srv.agent.Shutdown()
|
||||
|
||||
// Wait for leader
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
req, err := http.NewRequest("GET", "/v1/internal/ui/nodes/dc1", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
resp := httptest.NewRecorder()
|
||||
obj, err := srv.UINodes(resp, req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
assertIndex(t, resp)
|
||||
|
||||
// Should be 1 node for the server
|
||||
nodes := obj.(structs.NodeDump)
|
||||
if len(nodes) != 1 {
|
||||
t.Fatalf("bad: %v", obj)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue