diff --git a/api/catalog.go b/api/catalog.go index 36b088249e..babfc9a1df 100644 --- a/api/catalog.go +++ b/api/catalog.go @@ -4,6 +4,7 @@ type Node struct { ID string Node string Address string + Datacenter string TaggedAddresses map[string]string Meta map[string]string CreateIndex uint64 @@ -14,6 +15,7 @@ type CatalogService struct { ID string Node string Address string + Datacenter string TaggedAddresses map[string]string NodeMeta map[string]string ServiceID string diff --git a/api/catalog_test.go b/api/catalog_test.go index c418f85486..3a1a013938 100644 --- a/api/catalog_test.go +++ b/api/catalog_test.go @@ -54,6 +54,10 @@ func TestCatalog_Nodes(t *testing.T) { return false, fmt.Errorf("Bad: %v", nodes[0]) } + if nodes[0].Datacenter != "dc1" { + return false, fmt.Errorf("Bad datacenter: %v", nodes[0]) + } + return true, nil }); err != nil { t.Fatal(err) @@ -92,6 +96,10 @@ func TestCatalog_Nodes_MetaFilter(t *testing.T) { return false, fmt.Errorf("Bad: %v", nodes[0].Meta) } + if nodes[0].Datacenter != "dc1" { + return false, fmt.Errorf("Bad datacenter: %v", nodes[0]) + } + return true, nil }); err != nil { t.Fatal(err) @@ -216,6 +224,10 @@ func TestCatalog_Service(t *testing.T) { return false, fmt.Errorf("Bad: %v", services) } + if services[0].Datacenter != "dc1" { + return false, fmt.Errorf("Bad datacenter: %v", services[0]) + } + return true, nil }); err != nil { t.Fatal(err) @@ -246,6 +258,10 @@ func TestCatalog_Service_NodeMetaFilter(t *testing.T) { return false, fmt.Errorf("Bad: %v", services) } + if services[0].Datacenter != "dc1" { + return false, fmt.Errorf("Bad datacenter: %v", services[0]) + } + return true, nil }); err != nil { t.Fatal(err) @@ -278,6 +294,10 @@ func TestCatalog_Node(t *testing.T) { return false, fmt.Errorf("Bad: %v", info) } + if info.Node.Datacenter != "dc1" { + return false, fmt.Errorf("Bad datacenter: %v", info) + } + return true, nil }); err != nil { t.Fatal(err) diff --git a/api/health_test.go b/api/health_test.go index c697d4e569..877d9a5d57 100644 --- a/api/health_test.go +++ b/api/health_test.go @@ -269,6 +269,9 @@ func TestHealth_Service(t *testing.T) { if _, ok := checks[0].Node.TaggedAddresses["wan"]; !ok { return false, fmt.Errorf("Bad: %v", checks[0].Node) } + if checks[0].Node.Datacenter != "dc1" { + return false, fmt.Errorf("Bad datacenter: %v", checks[0].Node) + } return true, nil }); err != nil { t.Fatal(err) @@ -299,6 +302,9 @@ func TestHealth_Service_NodeMetaFilter(t *testing.T) { if _, ok := checks[0].Node.TaggedAddresses["wan"]; !ok { return false, fmt.Errorf("Bad: %v", checks[0].Node) } + if checks[0].Node.Datacenter != "dc1" { + return false, fmt.Errorf("Bad datacenter: %v", checks[0].Node) + } return true, nil }); err != nil { t.Fatal(err) diff --git a/api/prepared_query_test.go b/api/prepared_query_test.go index 84ec1f822b..d29714e8b0 100644 --- a/api/prepared_query_test.go +++ b/api/prepared_query_test.go @@ -117,6 +117,9 @@ func TestPreparedQuery(t *testing.T) { if wan, ok := results.Nodes[0].Node.TaggedAddresses["wan"]; !ok || wan != "127.0.0.1" { t.Fatalf("bad: %v", results) } + if results.Nodes[0].Node.Datacenter != "dc1" { + t.Fatalf("bad datacenter: %v", results) + } // Delete it. _, err = query.Delete(def.ID, nil) diff --git a/consul/state/catalog.go b/consul/state/catalog.go index ef44d40383..b8ea5d1c4a 100644 --- a/consul/state/catalog.go +++ b/consul/state/catalog.go @@ -89,6 +89,7 @@ func (s *StateStore) ensureRegistrationTxn(tx *memdb.Txn, idx uint64, req *struc ID: req.ID, Node: req.Node, Address: req.Address, + Datacenter: req.Datacenter, TaggedAddresses: req.TaggedAddresses, Meta: req.NodeMeta, } @@ -684,6 +685,7 @@ func (s *StateStore) parseServiceNodes(tx *memdb.Txn, ws memdb.WatchSet, service node := n.(*structs.Node) s.ID = node.ID s.Address = node.Address + s.Datacenter = node.Datacenter s.TaggedAddresses = node.TaggedAddresses s.NodeMeta = node.Meta diff --git a/consul/structs/structs.go b/consul/structs/structs.go index 0805dbf4cf..c874fbd77a 100644 --- a/consul/structs/structs.go +++ b/consul/structs/structs.go @@ -5,14 +5,14 @@ import ( "fmt" "math/rand" "reflect" + "regexp" + "strings" "time" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/types" "github.com/hashicorp/go-msgpack/codec" "github.com/hashicorp/serf/coordinate" - "regexp" - "strings" ) var ( @@ -235,6 +235,7 @@ func (r *RegisterRequest) ChangesNode(node *Node) bool { if r.ID != node.ID || r.Node != node.Node || r.Address != node.Address || + r.Datacenter != node.Datacenter || !reflect.DeepEqual(r.TaggedAddresses, node.TaggedAddresses) || !reflect.DeepEqual(r.NodeMeta, node.Meta) { return true @@ -322,6 +323,7 @@ type Node struct { ID types.NodeID Node string Address string + Datacenter string TaggedAddresses map[string]string Meta map[string]string @@ -387,6 +389,7 @@ type ServiceNode struct { ID types.NodeID Node string Address string + Datacenter string TaggedAddresses map[string]string NodeMeta map[string]string ServiceID string diff --git a/consul/structs/structs_test.go b/consul/structs/structs_test.go index 56b6dcf1f6..2c2349e313 100644 --- a/consul/structs/structs_test.go +++ b/consul/structs/structs_test.go @@ -110,6 +110,7 @@ func TestStructs_RegisterRequest_ChangesNode(t *testing.T) { ID: types.NodeID("40e4a748-2192-161a-0510-9bf59fe950b5"), Node: "test", Address: "127.0.0.1", + Datacenter: "dc1", TaggedAddresses: make(map[string]string), NodeMeta: map[string]string{ "role": "server", @@ -120,6 +121,7 @@ func TestStructs_RegisterRequest_ChangesNode(t *testing.T) { ID: types.NodeID("40e4a748-2192-161a-0510-9bf59fe950b5"), Node: "test", Address: "127.0.0.1", + Datacenter: "dc1", TaggedAddresses: make(map[string]string), Meta: map[string]string{ "role": "server", @@ -155,6 +157,7 @@ func TestStructs_RegisterRequest_ChangesNode(t *testing.T) { check(func() { req.ID = "nope" }, func() { req.ID = types.NodeID("40e4a748-2192-161a-0510-9bf59fe950b5") }) check(func() { req.Node = "nope" }, func() { req.Node = "test" }) check(func() { req.Address = "127.0.0.2" }, func() { req.Address = "127.0.0.1" }) + check(func() { req.Datacenter = "dc2" }, func() { req.Datacenter = "dc1" }) check(func() { req.TaggedAddresses["wan"] = "nope" }, func() { delete(req.TaggedAddresses, "wan") }) check(func() { req.NodeMeta["invalid"] = "nope" }, func() { delete(req.NodeMeta, "invalid") }) @@ -166,9 +169,10 @@ func TestStructs_RegisterRequest_ChangesNode(t *testing.T) { // testServiceNode gives a fully filled out ServiceNode instance. func testServiceNode() *ServiceNode { return &ServiceNode{ - ID: types.NodeID("40e4a748-2192-161a-0510-9bf59fe950b5"), - Node: "node1", - Address: "127.0.0.1", + ID: types.NodeID("40e4a748-2192-161a-0510-9bf59fe950b5"), + Node: "node1", + Address: "127.0.0.1", + Datacenter: "dc1", TaggedAddresses: map[string]string{ "hello": "world", }, @@ -198,6 +202,7 @@ func TestStructs_ServiceNode_PartialClone(t *testing.T) { // the rest of the contents. if clone.ID != "" || clone.Address != "" || + clone.Datacenter != "" || len(clone.TaggedAddresses) != 0 || len(clone.NodeMeta) != 0 { t.Fatalf("bad: %v", clone) @@ -205,6 +210,7 @@ func TestStructs_ServiceNode_PartialClone(t *testing.T) { sn.ID = "" sn.Address = "" + sn.Datacenter = "" sn.TaggedAddresses = nil sn.NodeMeta = nil if !reflect.DeepEqual(sn, clone) { @@ -226,6 +232,7 @@ func TestStructs_ServiceNode_Conversions(t *testing.T) { // them out before we do the compare. sn.ID = "" sn.Address = "" + sn.Datacenter = "" sn.TaggedAddresses = nil sn.NodeMeta = nil if !reflect.DeepEqual(sn, sn2) { diff --git a/website/source/api/catalog.html.md b/website/source/api/catalog.html.md index c784663a2a..377b71bc1a 100644 --- a/website/source/api/catalog.html.md +++ b/website/source/api/catalog.html.md @@ -274,6 +274,7 @@ $ curl \ "ID": "40e4a748-2192-161a-0510-9bf59fe950b5", "Node": "baz", "Address": "10.1.10.11", + "Datacenter": "dc1", "TaggedAddresses": { "lan": "10.1.10.11", "wan": "10.1.10.11" @@ -286,6 +287,7 @@ $ curl \ "ID": "8f246b77-f3e1-ff88-5b48-8ec93abf3e05", "Node": "foobar", "Address": "10.1.10.12", + "Datacenter": "dc2", "TaggedAddresses": { "lan": "10.1.10.11", "wan": "10.1.10.12" @@ -401,6 +403,7 @@ $ curl \ "ID": "40e4a748-2192-161a-0510-9bf59fe950b5", "Node": "foobar", "Address": "192.168.10.10", + "Datacenter": "dc1", "TaggedAddresses": { "lan": "192.168.10.10", "wan": "10.0.10.10" @@ -425,6 +428,9 @@ $ curl \ - `Address` is the IP address of the Consul node on which the service is registered. +- `Datacenter` is the data center of the Consul node on which the service is + registered. + - `TaggedAddresses` is the list of explicit LAN and WAN IP addresses for the agent @@ -495,6 +501,7 @@ $ curl \ "ID": "40e4a748-2192-161a-0510-9bf59fe950b5", "Node": "foobar", "Address": "10.1.10.12", + "Datacenter": "dc1", "TaggedAddresses": { "lan": "10.1.10.12", "wan": "10.1.10.12" diff --git a/website/source/api/health.html.markdown b/website/source/api/health.html.markdown index b0ce022003..cc75a25d2c 100644 --- a/website/source/api/health.html.markdown +++ b/website/source/api/health.html.markdown @@ -199,6 +199,7 @@ $ curl \ "ID": "40e4a748-2192-161a-0510-9bf59fe950b5", "Node": "foobar", "Address": "10.1.10.12", + "Datacenter": "dc1", "TaggedAddresses": { "lan": "10.1.10.12", "wan": "10.1.10.12" diff --git a/website/source/api/query.html.md b/website/source/api/query.html.md index d744c822c1..ed628da0d5 100644 --- a/website/source/api/query.html.md +++ b/website/source/api/query.html.md @@ -470,6 +470,7 @@ $ curl \ "ID": "40e4a748-2192-161a-0510-9bf59fe950b5", "Node": "foobar", "Address": "10.1.10.12", + "Datacenter": "dc1", "TaggedAddresses": { "lan": "10.1.10.12", "wan": "10.1.10.12"