diff --git a/command/agent/http.go b/command/agent/http.go index ec306d00b..681e19ff3 100644 --- a/command/agent/http.go +++ b/command/agent/http.go @@ -109,6 +109,8 @@ func (s *HTTPServer) registerHandlers(enableDebug bool) { 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/regions", s.wrap(s.RegionsListRequest)) + s.mux.HandleFunc("/v1/status/leader", s.wrap(s.StatusLeaderRequest)) s.mux.HandleFunc("/v1/status/peers", s.wrap(s.StatusPeersRequest)) diff --git a/command/agent/regions_endpoint.go b/command/agent/regions_endpoint.go new file mode 100644 index 000000000..c7f7f1330 --- /dev/null +++ b/command/agent/regions_endpoint.go @@ -0,0 +1,24 @@ +package agent + +import ( + "net/http" + + "github.com/hashicorp/nomad/nomad/structs" +) + +func (s *HTTPServer) RegionsListRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) { + if req.Method != "GET" { + return nil, CodedError(405, ErrInvalidMethod) + } + + var args structs.GenericRequest + if s.parse(resp, req, &args.Region, &args.QueryOptions) { + return nil, nil + } + + var regions []string + if err := s.agent.RPC("Region.List", &args, ®ions); err != nil { + return nil, err + } + return regions, nil +} diff --git a/nomad/regions_endpoint.go b/nomad/regions_endpoint.go new file mode 100644 index 000000000..6ca27feea --- /dev/null +++ b/nomad/regions_endpoint.go @@ -0,0 +1,18 @@ +package nomad + +import "github.com/hashicorp/nomad/nomad/structs" + +// Region is used to query and list the known regions +type Region struct { + srv *Server +} + +// List is used to list all of the known regions. +func (r *Region) List(args *structs.GenericRequest, reply *[]string) error { + if done, err := r.srv.forward("Region.List", args, args, reply); done { + return err + } + + *reply = r.srv.Regions() + return nil +} diff --git a/nomad/server.go b/nomad/server.go index 1c16f55d0..ca5b20c23 100644 --- a/nomad/server.go +++ b/nomad/server.go @@ -134,6 +134,7 @@ type endpoints struct { Eval *Eval Plan *Plan Alloc *Alloc + Region *Region } // NewServer is used to construct a new Nomad server from the @@ -353,6 +354,7 @@ func (s *Server) setupRPC(tlsWrap tlsutil.DCWrapper) error { s.endpoints.Eval = &Eval{s} s.endpoints.Plan = &Plan{s} s.endpoints.Alloc = &Alloc{s} + s.endpoints.Region = &Region{s} // Register the handlers s.rpcServer.Register(s.endpoints.Status) @@ -361,6 +363,7 @@ func (s *Server) setupRPC(tlsWrap tlsutil.DCWrapper) error { s.rpcServer.Register(s.endpoints.Eval) s.rpcServer.Register(s.endpoints.Plan) s.rpcServer.Register(s.endpoints.Alloc) + s.rpcServer.Register(s.endpoints.Region) list, err := net.ListenTCP("tcp", s.config.RPCAddr) if err != nil { @@ -612,6 +615,18 @@ func (s *Server) State() *state.StateStore { return s.fsm.State() } +// Regions returns the known regions in the cluster. +func (s *Server) Regions() []string { + s.peerLock.Lock() + defer s.peerLock.Unlock() + + regions := make([]string, 0, len(s.peers)) + for region, _ := range s.peers { + regions = append(regions, region) + } + return regions +} + // inmemCodec is used to do an RPC call without going over a network type inmemCodec struct { method string