From e39217433b1264953e4c95fda056c917b3b24544 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Mon, 23 Nov 2015 23:12:06 -0800 Subject: [PATCH] nomad: include datacenter names in regions reply --- ...regions_endpoint.go => region_endpoint.go} | 2 +- command/agent/region_endpoint_test.go | 11 +++++++--- nomad/regions_endpoint.go | 8 +++---- nomad/regions_endpoint_test.go | 12 +++++++--- nomad/server.go | 22 ++++++++++++++----- nomad/server_test.go | 10 +++++++-- website/source/docs/http/regions.html.md | 13 ++++++++--- 7 files changed, 57 insertions(+), 21 deletions(-) rename command/agent/{regions_endpoint.go => region_endpoint.go} (92%) diff --git a/command/agent/regions_endpoint.go b/command/agent/region_endpoint.go similarity index 92% rename from command/agent/regions_endpoint.go rename to command/agent/region_endpoint.go index 538adefb4f72..aefcd606018b 100644 --- a/command/agent/regions_endpoint.go +++ b/command/agent/region_endpoint.go @@ -16,7 +16,7 @@ func (s *HTTPServer) RegionListRequest(resp http.ResponseWriter, req *http.Reque return nil, nil } - var regions []string + regions := make(map[string][]string) if err := s.agent.RPC("Region.List", &args, ®ions); err != nil { return nil, err } diff --git a/command/agent/region_endpoint_test.go b/command/agent/region_endpoint_test.go index 006c7a1596d2..044f96de76bd 100644 --- a/command/agent/region_endpoint_test.go +++ b/command/agent/region_endpoint_test.go @@ -3,6 +3,7 @@ package agent import ( "net/http" "net/http/httptest" + "reflect" "testing" ) @@ -21,9 +22,13 @@ func TestHTTP_RegionList(t *testing.T) { t.Fatalf("err: %v", err) } - out := obj.([]string) - if len(out) != 1 || out[0] != "global" { - t.Fatalf("unexpected regions: %#v", out) + expect := map[string][]string{ + "global": []string{"dc1"}, + } + + out := obj.(map[string][]string) + if !reflect.DeepEqual(out, expect) { + t.Fatalf("expect: %v, got: %v", expect, out) } }) } diff --git a/nomad/regions_endpoint.go b/nomad/regions_endpoint.go index b9d2cd0f14b5..b360fd17a32e 100644 --- a/nomad/regions_endpoint.go +++ b/nomad/regions_endpoint.go @@ -7,10 +7,10 @@ type Region struct { srv *Server } -// List is used to list all of the known regions. No leader forwarding is -// required for this endpoint because memberlist is used to populate the -// peers list we read from. -func (r *Region) List(args *structs.GenericRequest, reply *[]string) error { +// List is used to list all of the known regions and datacenters. No leader +// forwarding is required for this endpoint because memberlist is used to +// populate the peers list we read from. +func (r *Region) List(args *structs.GenericRequest, reply *map[string][]string) error { *reply = r.srv.Regions() return nil } diff --git a/nomad/regions_endpoint_test.go b/nomad/regions_endpoint_test.go index cca212427c2e..7956ca359420 100644 --- a/nomad/regions_endpoint_test.go +++ b/nomad/regions_endpoint_test.go @@ -2,6 +2,7 @@ package nomad import ( "fmt" + "reflect" "testing" "github.com/hashicorp/net-rpc-msgpackrpc" @@ -29,15 +30,20 @@ func TestRegionList(t *testing.T) { t.Fatalf("Failed joining: %v (%d joined)", err, n) } + expect := map[string][]string{ + "region1": []string{"dc1"}, + "region2": []string{"dc1"}, + } + // Query the regions list testutil.WaitForResult(func() (bool, error) { var arg structs.GenericRequest - var out []string + var out map[string][]string if err := msgpackrpc.CallWithCodec(codec, "Region.List", &arg, &out); err != nil { t.Fatalf("err: %v", err) } - if len(out) != 2 || out[0] != "region1" || out[1] != "region2" { - t.Fatalf("unexpected regions: %v", out) + if !reflect.DeepEqual(out, expect) { + t.Fatalf("expect: %v, got: %v", expect, out) } return true, nil }, func(err error) { diff --git a/nomad/server.go b/nomad/server.go index cfedb6aef29f..687bd9c1d80c 100644 --- a/nomad/server.go +++ b/nomad/server.go @@ -615,14 +615,26 @@ func (s *Server) State() *state.StateStore { return s.fsm.State() } -// Regions returns the known regions in the cluster. -func (s *Server) Regions() []string { +// Regions returns the known regions in the cluster along with a list +// of the datacenters within each region. +func (s *Server) Regions() map[string][]string { s.peerLock.RLock() defer s.peerLock.RUnlock() - regions := make([]string, 0, len(s.peers)) - for region, _ := range s.peers { - regions = append(regions, region) + regions := make(map[string][]string, len(s.peers)) + for region, servers := range s.peers { + // Collect all the DC's + var dcs []string + seen := make(map[string]struct{}) + for _, srv := range servers { + if _, ok := seen[srv.Datacenter]; !ok { + dcs = append(dcs, srv.Datacenter) + } + seen[srv.Datacenter] = struct{}{} + } + + // Add the region + regions[region] = dcs } return regions } diff --git a/nomad/server_test.go b/nomad/server_test.go index 1ee4e7a65ffb..060a0241b1f4 100644 --- a/nomad/server_test.go +++ b/nomad/server_test.go @@ -4,6 +4,7 @@ import ( "fmt" "io/ioutil" "net" + "reflect" "sync/atomic" "testing" "time" @@ -108,11 +109,16 @@ func TestServer_Regions(t *testing.T) { t.Fatalf("Failed joining: %v (%d joined)", err, n) } + expect := map[string][]string{ + "region1": []string{"dc1"}, + "region2": []string{"dc1"}, + } + // Try listing the regions testutil.WaitForResult(func() (bool, error) { out := s1.Regions() - if len(out) != 2 || out[0] != "region1" || out[1] != "region2" { - return false, fmt.Errorf("unexpected regions: %v", out) + if !reflect.DeepEqual(out, expect) { + return false, fmt.Errorf("expect: %v, got: %v", expect, out) } return true, nil }, func(err error) { diff --git a/website/source/docs/http/regions.html.md b/website/source/docs/http/regions.html.md index 5de35509c597..ef86879fc3b8 100644 --- a/website/source/docs/http/regions.html.md +++ b/website/source/docs/http/regions.html.md @@ -3,7 +3,8 @@ layout: "http" page_title: "HTTP API: /v1/regions" sidebar_current: "docs-http-regions" description: > - The '/v1/regions' endpoint lists the known cluster regions. + The '/v1/regions' endpoint lists the known cluster regions and their + datacenters. --- # /v1/regions @@ -13,7 +14,7 @@ description: >
Description
- Returns the known region names. + Returns a summary of the known regions, including the datacenter names.
Method
@@ -31,7 +32,13 @@ description: >
```javascript - ["region1","region2"] + { + "global": [ + "dc1", + "dc2" + ], + ... + } ```