Merge branch 'MerlinDMC-feature/configurable_service_address'

This commit is contained in:
Armon Dadgar 2015-01-08 12:08:41 -08:00
commit d1bd99b1e3
12 changed files with 201 additions and 79 deletions

View File

@ -409,17 +409,17 @@ RPC:
}
// Add the node record
records := d.formatNodeRecord(&out.NodeServices.Node, req.Question[0].Name,
qType, d.config.NodeTTL)
records := d.formatNodeRecord(&out.NodeServices.Node, out.NodeServices.Node.Address,
req.Question[0].Name, qType, d.config.NodeTTL)
if records != nil {
resp.Answer = append(resp.Answer, records...)
}
}
// formatNodeRecord takes a Node and returns an A, AAAA, or CNAME record
func (d *DNSServer) formatNodeRecord(node *structs.Node, qName string, qType uint16, ttl time.Duration) (records []dns.RR) {
func (d *DNSServer) formatNodeRecord(node *structs.Node, addr, qName string, qType uint16, ttl time.Duration) (records []dns.RR) {
// Parse the IP
ip := net.ParseIP(node.Address)
ip := net.ParseIP(addr)
var ipv4 net.IP
if ip != nil {
ipv4 = ip.To4()
@ -457,7 +457,7 @@ func (d *DNSServer) formatNodeRecord(node *structs.Node, qName string, qType uin
Class: dns.ClassINET,
Ttl: uint32(ttl / time.Second),
},
Target: dns.Fqdn(node.Address),
Target: dns.Fqdn(addr),
}
records = append(records, cnRec)
@ -584,13 +584,17 @@ func (d *DNSServer) serviceNodeRecords(nodes structs.CheckServiceNodes, req, res
// Avoid duplicate entries, possible if a node has
// the same service on multiple ports, etc.
addr := node.Node.Address
if node.Service.Address != "" {
addr = node.Service.Address
}
if _, ok := handled[addr]; ok {
continue
}
handled[addr] = struct{}{}
// Add the node record
records := d.formatNodeRecord(&node.Node, qName, qType, ttl)
records := d.formatNodeRecord(&node.Node, addr, qName, qType, ttl)
if records != nil {
resp.Answer = append(resp.Answer, records...)
}
@ -603,7 +607,7 @@ func (d *DNSServer) serviceSRVRecords(dc string, nodes structs.CheckServiceNodes
for _, node := range nodes {
// Avoid duplicate entries, possible if a node has
// the same service the same port, etc.
tuple := fmt.Sprintf("%s:%d", node.Node.Node, node.Service.Port)
tuple := fmt.Sprintf("%s:%s:%d", node.Node.Node, node.Service.Address, node.Service.Port)
if _, ok := handled[tuple]; ok {
continue
}
@ -624,8 +628,14 @@ func (d *DNSServer) serviceSRVRecords(dc string, nodes structs.CheckServiceNodes
}
resp.Answer = append(resp.Answer, srvRec)
// Determine advertised address
addr := node.Node.Address
if node.Service.Address != "" {
addr = node.Service.Address
}
// Add the extra record
records := d.formatNodeRecord(&node.Node, srvRec.Target, dns.TypeANY, ttl)
records := d.formatNodeRecord(&node.Node, addr, srvRec.Target, dns.TypeANY, ttl)
if records != nil {
resp.Extra = append(resp.Extra, records...)
}

View File

@ -430,6 +430,7 @@ func TestDNS_ReverseLookup_IPV6(t *testing.T) {
t.Fatalf("Bad: %#v", ptrRec)
}
}
func TestDNS_ServiceLookup(t *testing.T) {
dir, srv := makeDNSServer(t)
defer os.RemoveAll(dir)
@ -497,6 +498,74 @@ func TestDNS_ServiceLookup(t *testing.T) {
}
}
func TestDNS_ServiceLookup_ServiceAddress(t *testing.T) {
dir, srv := makeDNSServer(t)
defer os.RemoveAll(dir)
defer srv.agent.Shutdown()
testutil.WaitForLeader(t, srv.agent.RPC, "dc1")
// Register node
args := &structs.RegisterRequest{
Datacenter: "dc1",
Node: "foo",
Address: "127.0.0.1",
Service: &structs.NodeService{
Service: "db",
Tags: []string{"master"},
Address: "127.0.0.2",
Port: 12345,
},
}
var out struct{}
if err := srv.agent.RPC("Catalog.Register", args, &out); err != nil {
t.Fatalf("err: %v", err)
}
m := new(dns.Msg)
m.SetQuestion("db.service.consul.", dns.TypeSRV)
c := new(dns.Client)
addr, _ := srv.agent.config.ClientListener("", srv.agent.config.Ports.DNS)
in, _, err := c.Exchange(m, addr.String())
if err != nil {
t.Fatalf("err: %v", err)
}
if len(in.Answer) != 1 {
t.Fatalf("Bad: %#v", in)
}
srvRec, ok := in.Answer[0].(*dns.SRV)
if !ok {
t.Fatalf("Bad: %#v", in.Answer[0])
}
if srvRec.Port != 12345 {
t.Fatalf("Bad: %#v", srvRec)
}
if srvRec.Target != "foo.node.dc1.consul." {
t.Fatalf("Bad: %#v", srvRec)
}
if srvRec.Hdr.Ttl != 0 {
t.Fatalf("Bad: %#v", in.Answer[0])
}
aRec, ok := in.Extra[0].(*dns.A)
if !ok {
t.Fatalf("Bad: %#v", in.Extra[0])
}
if aRec.Hdr.Name != "foo.node.dc1.consul." {
t.Fatalf("Bad: %#v", in.Extra[0])
}
if aRec.A.String() != "127.0.0.2" {
t.Fatalf("Bad: %#v", in.Extra[0])
}
if aRec.Hdr.Ttl != 0 {
t.Fatalf("Bad: %#v", in.Extra[0])
}
}
func TestDNS_CaseInsensitiveServiceLookup(t *testing.T) {
dir, srv := makeDNSServer(t)
defer os.RemoveAll(dir)

View File

@ -77,6 +77,24 @@ func TestAgentAntiEntropy_Services(t *testing.T) {
t.Fatalf("err: %v", err)
}
// Exists both, different address (update)
srv5 := &structs.NodeService{
ID: "api",
Service: "api",
Tags: []string{},
Address: "127.0.0.10",
Port: 8000,
}
agent.state.AddService(srv5)
srv5_mod := new(structs.NodeService)
*srv5_mod = *srv5
srv5_mod.Address = "127.0.0.1"
args.Service = srv5_mod
if err := agent.RPC("Catalog.Register", args, &out); err != nil {
t.Fatalf("err: %v", err)
}
// Trigger anti-entropy run and wait
agent.StartSync()
time.Sleep(200 * time.Millisecond)
@ -91,8 +109,8 @@ func TestAgentAntiEntropy_Services(t *testing.T) {
t.Fatalf("err: %v", err)
}
// We should have 4 services (consul included)
if len(services.NodeServices.Services) != 4 {
// We should have 5 services (consul included)
if len(services.NodeServices.Services) != 5 {
t.Fatalf("bad: %v", services.NodeServices.Services)
}
@ -111,6 +129,10 @@ func TestAgentAntiEntropy_Services(t *testing.T) {
if !reflect.DeepEqual(serv, srv3) {
t.Fatalf("bad: %v %v", serv, srv3)
}
case "api":
if !reflect.DeepEqual(serv, srv5) {
t.Fatalf("bad: %v %v", serv, srv5)
}
case "consul":
// ignore
default:
@ -119,10 +141,10 @@ func TestAgentAntiEntropy_Services(t *testing.T) {
}
// Check the local state
if len(agent.state.services) != 4 {
if len(agent.state.services) != 5 {
t.Fatalf("bad: %v", agent.state.services)
}
if len(agent.state.serviceStatus) != 4 {
if len(agent.state.serviceStatus) != 5 {
t.Fatalf("bad: %v", agent.state.serviceStatus)
}
for name, status := range agent.state.serviceStatus {

View File

@ -9,6 +9,7 @@ type ServiceDefinition struct {
ID string
Name string
Tags []string
Address string
Port int
Check CheckType
}
@ -18,6 +19,7 @@ func (s *ServiceDefinition) NodeService() *structs.NodeService {
ID: s.ID,
Service: s.Name,
Tags: s.Tags,
Address: s.Address,
Port: s.Port,
}
if ns.ID == "" && ns.Service != "" {

View File

@ -490,7 +490,7 @@ func TestCatalogListServices(t *testing.T) {
// Just add a node
s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, 5000})
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000})
if err := client.Call("Catalog.ListServices", &args, &out); err != nil {
t.Fatalf("err: %v", err)
@ -544,7 +544,7 @@ func TestCatalogListServices_Blocking(t *testing.T) {
go func() {
time.Sleep(100 * time.Millisecond)
s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, 5000})
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000})
}()
// Re-run the query
@ -625,7 +625,7 @@ func TestCatalogListServices_Stale(t *testing.T) {
// Inject a fake service
s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, 5000})
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000})
// Run the query, do not wait for leader!
if err := client.Call("Catalog.ListServices", &args, &out); err != nil {
@ -666,7 +666,7 @@ func TestCatalogListServiceNodes(t *testing.T) {
// Just add a node
s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, 5000})
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000})
if err := client.Call("Catalog.ServiceNodes", &args, &out); err != nil {
t.Fatalf("err: %v", err)
@ -709,8 +709,8 @@ func TestCatalogNodeServices(t *testing.T) {
// Just add a node
s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, 5000})
s1.fsm.State().EnsureService(3, "foo", &structs.NodeService{"web", "web", nil, 80})
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000})
s1.fsm.State().EnsureService(3, "foo", &structs.NodeService{"web", "web", nil, "127.0.0.1", 80})
if err := client.Call("Catalog.NodeServices", &args, &out); err != nil {
t.Fatalf("err: %v", err)

View File

@ -337,10 +337,10 @@ func TestFSM_SnapshotRestore(t *testing.T) {
// Add some state
fsm.state.EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
fsm.state.EnsureNode(2, structs.Node{"baz", "127.0.0.2"})
fsm.state.EnsureService(3, "foo", &structs.NodeService{"web", "web", nil, 80})
fsm.state.EnsureService(4, "foo", &structs.NodeService{"db", "db", []string{"primary"}, 5000})
fsm.state.EnsureService(5, "baz", &structs.NodeService{"web", "web", nil, 80})
fsm.state.EnsureService(6, "baz", &structs.NodeService{"db", "db", []string{"secondary"}, 5000})
fsm.state.EnsureService(3, "foo", &structs.NodeService{"web", "web", nil, "127.0.0.1", 80})
fsm.state.EnsureService(4, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000})
fsm.state.EnsureService(5, "baz", &structs.NodeService{"web", "web", nil, "127.0.0.2", 80})
fsm.state.EnsureService(6, "baz", &structs.NodeService{"db", "db", []string{"secondary"}, "127.0.0.2", 5000})
fsm.state.EnsureCheck(7, &structs.HealthCheck{
Node: "foo",
CheckID: "web",

View File

@ -591,6 +591,7 @@ func (s *StateStore) ensureServiceTxn(index uint64, node string, ns *structs.Nod
ServiceID: ns.ID,
ServiceName: ns.Service,
ServiceTags: ns.Tags,
ServiceAddress: ns.Address,
ServicePort: ns.Port,
}
@ -655,6 +656,7 @@ func (s *StateStore) parseNodeServices(tables MDBTables, tx *MDBTxn, name string
ID: service.ServiceID,
Service: service.ServiceName,
Tags: service.ServiceTags,
Address: service.ServiceAddress,
Port: service.ServicePort,
}
ns.Services[srv.ID] = srv
@ -1039,6 +1041,7 @@ func (s *StateStore) parseCheckServiceNodes(tx *MDBTxn, res []interface{}, err e
ID: srv.ServiceID,
Service: srv.ServiceName,
Tags: srv.ServiceTags,
Address: srv.ServiceAddress,
Port: srv.ServicePort,
}
nodes[i].Checks = checks
@ -1113,6 +1116,7 @@ func (s *StateStore) parseNodeInfo(tx *MDBTxn, res []interface{}, err error) str
ID: service.ServiceID,
Service: service.ServiceName,
Tags: service.ServiceTags,
Address: service.ServiceAddress,
Port: service.ServicePort,
}
info.Services = append(info.Services, srv)

View File

@ -24,7 +24,7 @@ func TestEnsureRegistration(t *testing.T) {
reg := &structs.RegisterRequest{
Node: "foo",
Address: "127.0.0.1",
Service: &structs.NodeService{"api", "api", nil, 5000},
Service: &structs.NodeService{"api", "api", nil, "", 5000},
Check: &structs.HealthCheck{
Node: "foo",
CheckID: "api",
@ -149,15 +149,15 @@ func TestEnsureService(t *testing.T) {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(11, "foo", &structs.NodeService{"api", "api", nil, 5000}); err != nil {
if err := store.EnsureService(11, "foo", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, 5001}); err != nil {
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5001}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(13, "foo", &structs.NodeService{"db", "db", []string{"master"}, 8000}); err != nil {
if err := store.EnsureService(13, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
@ -194,15 +194,15 @@ func TestEnsureService_DuplicateNode(t *testing.T) {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(11, "foo", &structs.NodeService{"api1", "api", nil, 5000}); err != nil {
if err := store.EnsureService(11, "foo", &structs.NodeService{"api1", "api", nil, "", 5000}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(12, "foo", &structs.NodeService{"api2", "api", nil, 5001}); err != nil {
if err := store.EnsureService(12, "foo", &structs.NodeService{"api2", "api", nil, "", 5001}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(13, "foo", &structs.NodeService{"api3", "api", nil, 5002}); err != nil {
if err := store.EnsureService(13, "foo", &structs.NodeService{"api3", "api", nil, "", 5002}); err != nil {
t.Fatalf("err: %v", err)
}
@ -247,7 +247,7 @@ func TestDeleteNodeService(t *testing.T) {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, 5000}); err != nil {
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
t.Fatalf("err: %v", err)
}
@ -295,11 +295,11 @@ func TestDeleteNodeService_One(t *testing.T) {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, 5000}); err != nil {
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(13, "foo", &structs.NodeService{"api2", "api", nil, 5001}); err != nil {
if err := store.EnsureService(13, "foo", &structs.NodeService{"api2", "api", nil, "", 5001}); err != nil {
t.Fatalf("err: %v", err)
}
@ -332,7 +332,7 @@ func TestDeleteNode(t *testing.T) {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(21, "foo", &structs.NodeService{"api", "api", nil, 5000}); err != nil {
if err := store.EnsureService(21, "foo", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
t.Fatalf("err: %v", err)
}
@ -391,15 +391,15 @@ func TestGetServices(t *testing.T) {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(32, "foo", &structs.NodeService{"api", "api", nil, 5000}); err != nil {
if err := store.EnsureService(32, "foo", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(33, "foo", &structs.NodeService{"db", "db", []string{"master"}, 8000}); err != nil {
if err := store.EnsureService(33, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(34, "bar", &structs.NodeService{"db", "db", []string{"slave"}, 8000}); err != nil {
if err := store.EnsureService(34, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
@ -441,23 +441,23 @@ func TestServiceNodes(t *testing.T) {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, 5000}); err != nil {
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(13, "bar", &structs.NodeService{"api", "api", nil, 5000}); err != nil {
if err := store.EnsureService(13, "bar", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(14, "foo", &structs.NodeService{"db", "db", []string{"master"}, 8000}); err != nil {
if err := store.EnsureService(14, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(15, "bar", &structs.NodeService{"db", "db", []string{"slave"}, 8000}); err != nil {
if err := store.EnsureService(15, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(16, "bar", &structs.NodeService{"db2", "db", []string{"slave"}, 8001}); err != nil {
if err := store.EnsureService(16, "bar", &structs.NodeService{"db2", "db", []string{"slave"}, "", 8001}); err != nil {
t.Fatalf("err: %v", err)
}
@ -532,15 +532,15 @@ func TestServiceTagNodes(t *testing.T) {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(17, "foo", &structs.NodeService{"db", "db", []string{"master"}, 8000}); err != nil {
if err := store.EnsureService(17, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(18, "foo", &structs.NodeService{"db2", "db", []string{"slave"}, 8001}); err != nil {
if err := store.EnsureService(18, "foo", &structs.NodeService{"db2", "db", []string{"slave"}, "", 8001}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(19, "bar", &structs.NodeService{"db", "db", []string{"slave"}, 8000}); err != nil {
if err := store.EnsureService(19, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
@ -580,15 +580,15 @@ func TestServiceTagNodes_MultipleTags(t *testing.T) {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(17, "foo", &structs.NodeService{"db", "db", []string{"master", "v2"}, 8000}); err != nil {
if err := store.EnsureService(17, "foo", &structs.NodeService{"db", "db", []string{"master", "v2"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(18, "foo", &structs.NodeService{"db2", "db", []string{"slave", "v2", "dev"}, 8001}); err != nil {
if err := store.EnsureService(18, "foo", &structs.NodeService{"db2", "db", []string{"slave", "v2", "dev"}, "", 8001}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(19, "bar", &structs.NodeService{"db", "db", []string{"slave", "v2"}, 8000}); err != nil {
if err := store.EnsureService(19, "bar", &structs.NodeService{"db", "db", []string{"slave", "v2"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
@ -656,15 +656,15 @@ func TestStoreSnapshot(t *testing.T) {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(10, "foo", &structs.NodeService{"db", "db", []string{"master"}, 8000}); err != nil {
if err := store.EnsureService(10, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(11, "foo", &structs.NodeService{"db2", "db", []string{"slave"}, 8001}); err != nil {
if err := store.EnsureService(11, "foo", &structs.NodeService{"db2", "db", []string{"slave"}, "", 8001}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(12, "bar", &structs.NodeService{"db", "db", []string{"slave"}, 8000}); err != nil {
if err := store.EnsureService(12, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
@ -849,10 +849,10 @@ func TestStoreSnapshot(t *testing.T) {
}
// Make some changes!
if err := store.EnsureService(23, "foo", &structs.NodeService{"db", "db", []string{"slave"}, 8000}); err != nil {
if err := store.EnsureService(23, "foo", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(24, "bar", &structs.NodeService{"db", "db", []string{"master"}, 8000}); err != nil {
if err := store.EnsureService(24, "bar", &structs.NodeService{"db", "db", []string{"master"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureNode(25, structs.Node{"baz", "127.0.0.3"}); err != nil {
@ -979,7 +979,7 @@ func TestEnsureCheck(t *testing.T) {
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, 8000}); err != nil {
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
check := &structs.HealthCheck{
@ -1075,7 +1075,7 @@ func TestDeleteNodeCheck(t *testing.T) {
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, 8000}); err != nil {
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
check := &structs.HealthCheck{
@ -1125,7 +1125,7 @@ func TestCheckServiceNodes(t *testing.T) {
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, 8000}); err != nil {
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
check := &structs.HealthCheck{
@ -1206,7 +1206,7 @@ func BenchmarkCheckServiceNodes(t *testing.B) {
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, 8000}); err != nil {
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
check := &structs.HealthCheck{
@ -1249,6 +1249,7 @@ func TestSS_Register_Deregister_Query(t *testing.T) {
"statsite-box-stats",
"statsite-box-stats",
nil,
"",
0}
if err := store.EnsureService(2, "foo", srv); err != nil {
t.Fatalf("err: %v", err)
@ -1258,6 +1259,7 @@ func TestSS_Register_Deregister_Query(t *testing.T) {
"statsite-share-stats",
"statsite-share-stats",
nil,
"",
0}
if err := store.EnsureService(3, "foo", srv); err != nil {
t.Fatalf("err: %v", err)
@ -1286,7 +1288,7 @@ func TestNodeInfo(t *testing.T) {
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, 8000}); err != nil {
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
check := &structs.HealthCheck{
@ -1345,13 +1347,13 @@ func TestNodeDump(t *testing.T) {
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, 8000}); err != nil {
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureNode(3, structs.Node{"baz", "127.0.0.2"}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(4, "baz", &structs.NodeService{"db1", "db", []string{"master"}, 8000}); err != nil {
if err := store.EnsureService(4, "baz", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000}); err != nil {
t.Fatalf("err: %v", err)
}
@ -2459,7 +2461,7 @@ func TestSessionInvalidate_DeleteNodeService(t *testing.T) {
if err := store.EnsureNode(11, structs.Node{"foo", "127.0.0.1"}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, 5000}); err != nil {
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
t.Fatalf("err: %v", err)
}
check := &structs.HealthCheck{

View File

@ -222,6 +222,7 @@ type ServiceNode struct {
ServiceID string
ServiceName string
ServiceTags []string
ServiceAddress string
ServicePort int
}
type ServiceNodes []ServiceNode
@ -231,6 +232,7 @@ type NodeService struct {
ID string
Service string
Tags []string
Address string
Port int
}
type NodeServices struct {

View File

@ -12,6 +12,7 @@ func TestEncodeDecode(t *testing.T) {
Address: "baz",
Service: &NodeService{
Service: "test",
Address: "127.0.0.2",
},
}
buf, err := Encode(RegisterRequestType, arg)

View File

@ -283,6 +283,7 @@ This endpoint is hit with a GET and returns a JSON body like this:
"ID": "redis",
"Service": "redis",
"Tags": null,
"Address": "",
"Port": 8000
}
}
@ -502,6 +503,7 @@ body must look like:
"master",
"v1"
],
"Address": "127.0.0.1",
"Port": 8000,
"Check": {
"Script": "/usr/local/bin/check_redis.py",
@ -513,8 +515,9 @@ body must look like:
The `Name` field is mandatory, If an `ID` is not provided, it is set to `Name`.
You cannot have duplicate `ID` entries per agent, so it may be necessary to provide an ID.
`Tags`, `Port` and `Check` are optional. If `Check` is provided, only one of `Script` and `Interval`
`Tags`, `Address`, `Port` and `Check` are optional. If `Check` is provided, only one of `Script` and `Interval`
or `TTL` should be provided. There is more information about checks [here](/docs/agent/checks.html).
The `Address` will default to that of the agent if not provided.
The created check will be named "service:\<ServiceId\>".
@ -568,6 +571,7 @@ body must look like:
"master",
"v1"
],
"Address": "127.0.0.1",
"Port": 8000
},
"Check": {
@ -588,7 +592,7 @@ the node with the catalog.
If the `Service` key is provided, then the service will also be registered. If
`ID` is not provided, it will be defaulted to `Service`. It is mandated that the
ID be node-unique. Both `Tags` and `Port` can be omitted.
ID be node-unique. The `Tags`, `Address` and `Port` fields can be omitted.
If the `Check` key is provided, then a health check will also be registered. It
is important to remember that this register API is very low level. This manipulates
@ -732,6 +736,7 @@ It returns a JSON body like this:
"ServiceID": "redis",
"ServiceName": "redis",
"ServiceTags": null,
"ServiceAddress": "",
"ServicePort": 8000
}
]

View File

@ -24,6 +24,7 @@ A service definition that is a script looks like:
"service": {
"name": "redis",
"tags": ["master"],
"address": "127.0.0.1",
"port": 8000,
"check": {
"script": "/usr/local/bin/check_redis.py",
@ -34,12 +35,14 @@ A service definition that is a script looks like:
```
A service definition must include a `name`, and may optionally provide
an `id`, `tags`, `port`, and `check`. The `id` is set to the `name` if not
an `id`, `tags`, `address`, `port`, and `check`. The `id` is set to the `name` if not
provided. It is required that all services have a unique ID per node, so if names
might conflict then unique ID's should be provided.
The `tags` is a list of opaque value to Consul, but can be used to distinguish
between "master" or "slave" nodes, different versions, or any other service level labels.
The `address` can be used to specify a service specific IP address. By default,
the IP address of the agent is used, and this does not need to be provided.
The `port` can be used as well to make a service oriented architecture
simpler to configure. This way the address and port of a service can
be discovered.
@ -76,6 +79,7 @@ Multiple services definitions can be provided at once using the `services`
"tags": [
"master"
],
"address": "127.0.0.1",
"port": 6000,
"check": {
"script": "/bin/check_redis -p 6000",
@ -90,6 +94,7 @@ Multiple services definitions can be provided at once using the `services`
"delayed",
"slave"
],
"address": "127.0.0.1",
"port": 7000,
"check": {
"script": "/bin/check_redis -p 7000",