diff --git a/command/agent/dns.go b/command/agent/dns.go index b1857c34ac..8778dedcb5 100644 --- a/command/agent/dns.go +++ b/command/agent/dns.go @@ -390,7 +390,7 @@ RPC: } // Add the node record - records := d.formatNodeRecord(&out.NodeServices.Node, out.NodeServices.Node.Address, + 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...) @@ -585,7 +585,7 @@ func (d *DNSServer) serviceNodeRecords(nodes structs.CheckServiceNodes, req, res handled[addr] = struct{}{} // Add the node record - records := d.formatNodeRecord(&node.Node, addr, qName, qType, ttl) + records := d.formatNodeRecord(node.Node, addr, qName, qType, ttl) if records != nil { resp.Answer = append(resp.Answer, records...) } @@ -626,7 +626,7 @@ func (d *DNSServer) serviceSRVRecords(dc string, nodes structs.CheckServiceNodes } // Add the extra record - records := d.formatNodeRecord(&node.Node, addr, 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...) } diff --git a/consul/acl_test.go b/consul/acl_test.go index 8983493699..702be3f95d 100644 --- a/consul/acl_test.go +++ b/consul/acl_test.go @@ -724,7 +724,7 @@ func TestACL_filterServices(t *testing.T) { func TestACL_filterServiceNodes(t *testing.T) { // Create some service nodes nodes := structs.ServiceNodes{ - structs.ServiceNode{ + &structs.ServiceNode{ Node: "node1", ServiceName: "foo", }, @@ -748,7 +748,7 @@ func TestACL_filterServiceNodes(t *testing.T) { func TestACL_filterNodeServices(t *testing.T) { // Create some node services services := structs.NodeServices{ - Node: structs.Node{ + Node: &structs.Node{ Node: "node1", }, Services: map[string]*structs.NodeService{ @@ -778,10 +778,10 @@ func TestACL_filterCheckServiceNodes(t *testing.T) { // Create some nodes nodes := structs.CheckServiceNodes{ structs.CheckServiceNode{ - Node: structs.Node{ + Node: &structs.Node{ Node: "node1", }, - Service: structs.NodeService{ + Service: &structs.NodeService{ ID: "foo", Service: "foo", }, diff --git a/consul/catalog_endpoint_test.go b/consul/catalog_endpoint_test.go index d85dfc4f46..9665c2f33e 100644 --- a/consul/catalog_endpoint_test.go +++ b/consul/catalog_endpoint_test.go @@ -267,7 +267,7 @@ func TestCatalogListNodes(t *testing.T) { testutil.WaitForLeader(t, s1.RPC, "dc1") // Just add a node - s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) testutil.WaitForResult(func() (bool, error) { msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out) @@ -317,12 +317,12 @@ func TestCatalogListNodes_StaleRaad(t *testing.T) { codec = codec1 // Inject fake data on the follower! - s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) } else { codec = codec2 // Inject fake data on the follower! - s2.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + s2.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) } args := structs.DCSpecificRequest{ @@ -458,7 +458,7 @@ func BenchmarkCatalogListNodes(t *testing.B) { defer codec.Close() // Just add a node - s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) args := structs.DCSpecificRequest{ Datacenter: "dc1", @@ -490,8 +490,8 @@ func TestCatalogListServices(t *testing.T) { testutil.WaitForLeader(t, s1.RPC, "dc1") // 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"}, "127.0.0.1", 5000, false}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) + s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000}) if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil { t.Fatalf("err: %v", err) @@ -544,8 +544,8 @@ func TestCatalogListServices_Blocking(t *testing.T) { start := time.Now() 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"}, "127.0.0.1", 5000, false}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) + s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000}) }() // Re-run the query @@ -625,8 +625,8 @@ func TestCatalogListServices_Stale(t *testing.T) { var out structs.IndexedServices // 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"}, "127.0.0.1", 5000, false}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) + s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000}) // Run the query, do not wait for leader! if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil { @@ -666,8 +666,8 @@ func TestCatalogListServiceNodes(t *testing.T) { testutil.WaitForLeader(t, s1.RPC, "dc1") // 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"}, "127.0.0.1", 5000, false}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) + s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000}) if err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &args, &out); err != nil { t.Fatalf("err: %v", err) @@ -709,9 +709,9 @@ func TestCatalogNodeServices(t *testing.T) { testutil.WaitForLeader(t, s1.RPC, "dc1") // 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"}, "127.0.0.1", 5000, false}) - s1.fsm.State().EnsureService(3, "foo", &structs.NodeService{"web", "web", nil, "127.0.0.1", 80, false}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) + s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000}) + s1.fsm.State().EnsureService(3, "foo", &structs.NodeService{ID: "web", Service: "web", Tags: nil, Address: "127.0.0.1", Port: 80}) if err := msgpackrpc.CallWithCodec(codec, "Catalog.NodeServices", &args, &out); err != nil { t.Fatalf("err: %v", err) diff --git a/consul/fsm_test.go b/consul/fsm_test.go index 28594de418..7795a9191a 100644 --- a/consul/fsm_test.go +++ b/consul/fsm_test.go @@ -341,12 +341,12 @@ func TestFSM_SnapshotRestore(t *testing.T) { defer fsm.Close() // 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, "127.0.0.1", 80, false}) - fsm.state.EnsureService(4, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000, false}) - fsm.state.EnsureService(5, "baz", &structs.NodeService{"web", "web", nil, "127.0.0.2", 80, false}) - fsm.state.EnsureService(6, "baz", &structs.NodeService{"db", "db", []string{"secondary"}, "127.0.0.2", 5000, false}) + fsm.state.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) + fsm.state.EnsureNode(2, structs.Node{Node: "baz", Address: "127.0.0.2"}) + fsm.state.EnsureService(3, "foo", &structs.NodeService{ID: "web", Service: "web", Tags: nil, Address: "127.0.0.1", Port: 80}) + fsm.state.EnsureService(4, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000}) + fsm.state.EnsureService(5, "baz", &structs.NodeService{ID: "web", Service: "web", Tags: nil, Address: "127.0.0.2", Port: 80}) + fsm.state.EnsureService(6, "baz", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"secondary"}, Address: "127.0.0.2", Port: 5000}) fsm.state.EnsureCheck(7, &structs.HealthCheck{ Node: "foo", CheckID: "web", @@ -747,7 +747,7 @@ func TestFSM_SessionCreate_Destroy(t *testing.T) { } defer fsm.Close() - fsm.state.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + fsm.state.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) fsm.state.EnsureCheck(2, &structs.HealthCheck{ Node: "foo", CheckID: "web", @@ -832,7 +832,7 @@ func TestFSM_KVSLock(t *testing.T) { } defer fsm.Close() - fsm.state.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + fsm.state.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) session := &structs.Session{ID: generateUUID(), Node: "foo"} fsm.state.SessionCreate(2, session) @@ -882,7 +882,7 @@ func TestFSM_KVSUnlock(t *testing.T) { } defer fsm.Close() - fsm.state.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + fsm.state.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) session := &structs.Session{ID: generateUUID(), Node: "foo"} fsm.state.SessionCreate(2, session) diff --git a/consul/kvs_endpoint_test.go b/consul/kvs_endpoint_test.go index cfaee046ef..bc582eb85c 100644 --- a/consul/kvs_endpoint_test.go +++ b/consul/kvs_endpoint_test.go @@ -605,7 +605,7 @@ func TestKVS_Apply_LockDelay(t *testing.T) { // Create and invalidate a session with a lock state := s1.fsm.State() - if err := state.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := state.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } session := &structs.Session{ diff --git a/consul/session_endpoint_test.go b/consul/session_endpoint_test.go index 5e76da0938..dc7bd3e597 100644 --- a/consul/session_endpoint_test.go +++ b/consul/session_endpoint_test.go @@ -20,7 +20,7 @@ func TestSessionEndpoint_Apply(t *testing.T) { testutil.WaitForLeader(t, s1.RPC, "dc1") // Just add a node - s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) arg := structs.SessionRequest{ Datacenter: "dc1", @@ -79,7 +79,7 @@ func TestSessionEndpoint_DeleteApply(t *testing.T) { testutil.WaitForLeader(t, s1.RPC, "dc1") // Just add a node - s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) arg := structs.SessionRequest{ Datacenter: "dc1", @@ -141,7 +141,7 @@ func TestSessionEndpoint_Get(t *testing.T) { testutil.WaitForLeader(t, s1.RPC, "dc1") - s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) arg := structs.SessionRequest{ Datacenter: "dc1", Op: structs.SessionCreate, @@ -184,7 +184,7 @@ func TestSessionEndpoint_List(t *testing.T) { testutil.WaitForLeader(t, s1.RPC, "dc1") - s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) ids := []string{} for i := 0; i < 5; i++ { arg := structs.SessionRequest{ @@ -235,7 +235,7 @@ func TestSessionEndpoint_ApplyTimers(t *testing.T) { testutil.WaitForLeader(t, s1.RPC, "dc1") - s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) arg := structs.SessionRequest{ Datacenter: "dc1", Op: structs.SessionCreate, @@ -278,7 +278,7 @@ func TestSessionEndpoint_Renew(t *testing.T) { TTL := "10s" // the minimum allowed ttl ttl := 10 * time.Second - s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) ids := []string{} for i := 0; i < 5; i++ { arg := structs.SessionRequest{ @@ -436,8 +436,8 @@ func TestSessionEndpoint_NodeSessions(t *testing.T) { testutil.WaitForLeader(t, s1.RPC, "dc1") - s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) - s1.fsm.State().EnsureNode(1, structs.Node{"bar", "127.0.0.1"}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) + s1.fsm.State().EnsureNode(1, structs.Node{Node: "bar", Address: "127.0.0.1"}) ids := []string{} for i := 0; i < 10; i++ { arg := structs.SessionRequest{ diff --git a/consul/session_ttl_test.go b/consul/session_ttl_test.go index e732b5d017..4f855c654e 100644 --- a/consul/session_ttl_test.go +++ b/consul/session_ttl_test.go @@ -20,7 +20,7 @@ func TestInitializeSessionTimers(t *testing.T) { testutil.WaitForLeader(t, s1.RPC, "dc1") state := s1.fsm.State() - state.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + state.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) session := &structs.Session{ ID: generateUUID(), Node: "foo", @@ -58,7 +58,7 @@ func TestResetSessionTimer_Fault(t *testing.T) { // Create a session state := s1.fsm.State() - state.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + state.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) session := &structs.Session{ ID: generateUUID(), Node: "foo", @@ -90,7 +90,7 @@ func TestResetSessionTimer_NoTTL(t *testing.T) { // Create a session state := s1.fsm.State() - state.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + state.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) session := &structs.Session{ ID: generateUUID(), Node: "foo", @@ -201,7 +201,7 @@ func TestInvalidateSession(t *testing.T) { // Create a session state := s1.fsm.State() - state.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}) + state.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}) session := &structs.Session{ ID: generateUUID(), Node: "foo", diff --git a/consul/state/schema.go b/consul/state/schema.go index 59c6b63a7e..81faccb41d 100644 --- a/consul/state/schema.go +++ b/consul/state/schema.go @@ -177,6 +177,7 @@ func checksTableSchema() *memdb.TableSchema { Lowercase: true, }, }, + // TODO(slackpad): This one is new, where is it used? "node_service": &memdb.IndexSchema{ Name: "node_service", AllowMissing: true, @@ -304,6 +305,7 @@ func sessionChecksTableSchema() *memdb.TableSchema { }, }, }, + // TODO(slackpad): Where did these come from? "session": &memdb.IndexSchema{ Name: "session", AllowMissing: false, @@ -313,6 +315,7 @@ func sessionChecksTableSchema() *memdb.TableSchema { Lowercase: false, }, }, + // TODO(slackpad): Should this be called node_session? "node": &memdb.IndexSchema{ Name: "node", AllowMissing: false, diff --git a/consul/state/state_store.go b/consul/state/state_store.go index 0eb1689ebc..8731f051ef 100644 --- a/consul/state/state_store.go +++ b/consul/state/state_store.go @@ -34,7 +34,7 @@ var ( // pairs and more. The DB is entirely in-memory and is constructed // from the Raft log through the FSM. type StateStore struct { - logger *log.Logger + logger *log.Logger // TODO(slackpad) - Delete if unused! db *memdb.MemDB } @@ -168,7 +168,7 @@ func (s *StateStore) Nodes() (uint64, structs.Nodes, error) { if n.ModifyIndex > lindex { lindex = n.ModifyIndex } - results = append(results, node.(*structs.Node)) + results = append(results, n) } return lindex, results, nil } @@ -195,6 +195,9 @@ func (s *StateStore) deleteNodeTxn(idx uint64, nodeID string, tx *memdb.Txn) err if err != nil { return fmt.Errorf("node lookup failed: %s", err) } + if node == nil { + return nil + } // Delete all services associated with the node and update the service index services, err := tx.Get("services", "node", nodeID) @@ -275,6 +278,15 @@ func (s *StateStore) ensureServiceTxn(idx uint64, node string, svc *structs.Node entry.ModifyIndex = idx } + // Get the node + n, err := tx.First("nodes", "id", node) + if err != nil { + return fmt.Errorf("failed node lookup: %s", err) + } + if n == nil { + return ErrMissingNode + } + // Insert the service and update the index if err := tx.Insert("services", entry); err != nil { return fmt.Errorf("failed inserting service: %s", err) @@ -362,6 +374,9 @@ func (s *StateStore) deleteServiceTxn(idx uint64, nodeID, serviceID string, tx * if err != nil { return fmt.Errorf("failed service lookup: %s", err) } + if service == nil { + return nil + } // Delete any checks associated with the service checks, err := tx.Get("checks", "node_service", nodeID, serviceID) @@ -542,6 +557,9 @@ func (s *StateStore) deleteCheckTxn(idx uint64, node, id string, tx *memdb.Txn) if err != nil { return fmt.Errorf("check lookup failed: %s", err) } + if check == nil { + return nil + } // Delete the check from the DB and update the index if err := tx.Delete("checks", check); err != nil { @@ -876,6 +894,9 @@ func (s *StateStore) kvsDeleteTxn(idx uint64, key string, tx *memdb.Txn) error { if err != nil { return fmt.Errorf("failed kvs lookup: %s", err) } + if entry == nil { + return nil + } // Delete the entry and update the index if err := tx.Delete("kvs", entry); err != nil { @@ -1045,7 +1066,7 @@ func (s *StateStore) sessionCreateTxn(idx uint64, sess *structs.Session, tx *mem // Check that the check is not in critical state status := check.(*structs.HealthCheck).Status if status == structs.HealthCritical { - return fmt.Errorf("Check '%s' is in %s state", status) + return fmt.Errorf("Check '%s' is in %s state", checkID, status) } } @@ -1247,6 +1268,32 @@ func (s *StateStore) ACLGet(aclID string) (*structs.ACL, error) { return nil, nil } +// ACLList is used to list out all of the ACLs in the state store. +func (s *StateStore) ACLList() (uint64, []*structs.ACL, error) { + tx := s.db.Txn(false) + defer tx.Abort() + + // Query all of the ACLs in the state store + acls, err := tx.Get("acls", "id") + if err != nil { + return 0, nil, fmt.Errorf("failed acl lookup: %s", err) + } + + // Go over all of the ACLs and build the response + var result []*structs.ACL + var lindex uint64 + for acl := acls.Next(); acl != nil; acl = acls.Next() { + a := acl.(*structs.ACL) + result = append(result, a) + + // Accumulate the highest index + if a.ModifyIndex > lindex { + lindex = a.ModifyIndex + } + } + return lindex, result, nil +} + // ACLDelete is used to remove an existing ACL from the state store. If // the ACL does not exist this is a no-op and no error is returned. func (s *StateStore) ACLDelete(idx uint64, aclID string) error { @@ -1283,29 +1330,3 @@ func (s *StateStore) aclDeleteTxn(idx uint64, aclID string, tx *memdb.Txn) error } return nil } - -// ACLList is used to list out all of the ACLs in the state store. -func (s *StateStore) ACLList() (uint64, []*structs.ACL, error) { - tx := s.db.Txn(false) - defer tx.Abort() - - // Query all of the ACLs in the state store - acls, err := tx.Get("acls", "id") - if err != nil { - return 0, nil, fmt.Errorf("failed acl lookup: %s", err) - } - - // Go over all of the ACLs and build the response - var result []*structs.ACL - var lindex uint64 - for acl := acls.Next(); acl != nil; acl = acls.Next() { - a := acl.(*structs.ACL) - result = append(result, a) - - // Accumulate the highest index - if a.ModifyIndex > lindex { - lindex = a.ModifyIndex - } - } - return lindex, result, nil -} diff --git a/consul/state/state_store_test.go b/consul/state/state_store_test.go index 1d69d835eb..64d611dabe 100644 --- a/consul/state/state_store_test.go +++ b/consul/state/state_store_test.go @@ -55,7 +55,9 @@ func testRegisterService(t *testing.T, s *StateStore, idx uint64, nodeID, servic if err != nil { t.Fatalf("err: %s", err) } - if result, ok := service.(*structs.ServiceNode); !ok || result.ServiceID != serviceID { + if result, ok := service.(*structs.ServiceNode); !ok || + result.Node != nodeID || + result.ServiceID != serviceID { t.Fatalf("bad service: %#v", result) } } @@ -78,7 +80,10 @@ func testRegisterCheck(t *testing.T, s *StateStore, idx uint64, if err != nil { t.Fatalf("err: %s", err) } - if result, ok := c.(*structs.HealthCheck); !ok || result.CheckID != checkID { + if result, ok := c.(*structs.HealthCheck); !ok || + result.Node != nodeID || + result.ServiceID != serviceID || + result.CheckID != checkID { t.Fatalf("bad check: %#v", result) } } @@ -100,6 +105,16 @@ func testSetKey(t *testing.T, s *StateStore, idx uint64, key, value string) { } } +func TestStateStore_maxIndex(t *testing.T) { + s := testStateStore(t) + testRegisterNode(t, s, 0, "foo") + testRegisterNode(t, s, 1, "bar") + testRegisterService(t, s, 2, "foo", "consul") + if max := s.maxIndex("nodes", "services"); max != 2 { + t.Fatalf("bad max: %d", max) + } +} + func TestStateStore_EnsureNode(t *testing.T) { s := testStateStore(t) @@ -257,6 +272,15 @@ func TestStateStore_DeleteNode(t *testing.T) { t.Fatalf("bad index: %d (%s)", idx, tbl) } } + + // Deleting a nonexistent node should be idempotent and not return + // an error + if err := s.DeleteNode(4, "node1"); err != nil { + t.Fatalf("err: %s", err) + } + if idx := s.maxIndex("nodes"); idx != 3 { + t.Fatalf("bad index: %d", idx) + } } func TestStateStore_EnsureService(t *testing.T) { @@ -268,10 +292,6 @@ func TestStateStore_EnsureService(t *testing.T) { t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, res, err) } - // Register the nodes - testRegisterNode(t, s, 0, "node1") - testRegisterNode(t, s, 1, "node2") - // Create the service registration ns1 := &structs.NodeService{ ID: "service1", @@ -281,6 +301,15 @@ func TestStateStore_EnsureService(t *testing.T) { Port: 1111, } + // Creating a service without a node returns an error + if err := s.EnsureService(1, "node1", ns1); err != ErrMissingNode { + t.Fatalf("expected %#v, got: %#v", ErrMissingNode, err) + } + + // Register the nodes + testRegisterNode(t, s, 0, "node1") + testRegisterNode(t, s, 1, "node2") + // Service successfully registers into the state store if err = s.EnsureService(10, "node1", ns1); err != nil { t.Fatalf("err: %s", err) @@ -356,6 +385,11 @@ func TestStateStore_EnsureService(t *testing.T) { if svc, ok := out.Services["service1"]; !ok || svc.Address != "1.1.1.2" { t.Fatalf("bad: %#v", svc) } + + // Index tables were updated + if idx := s.maxIndex("services"); idx != 40 { + t.Fatalf("bad index: %d", idx) + } } func TestStateStore_DeleteService(t *testing.T) { @@ -393,6 +427,15 @@ func TestStateStore_DeleteService(t *testing.T) { if idx := s.maxIndex("checks"); idx != 4 { t.Fatalf("bad index: %d", idx) } + + // Deleting a nonexistent service should be idempotent and not return an + // error + if err := s.DeleteService(5, "node1", "service1"); err != nil { + t.Fatalf("err: %s", err) + } + if idx := s.maxIndex("services"); idx != 4 { + t.Fatalf("bad index: %d", idx) + } } func TestStateStore_EnsureCheck(t *testing.T) { @@ -504,6 +547,45 @@ func TestStateStore_EnsureCheck_defaultStatus(t *testing.T) { } } +func TestStateStore_NodeChecks(t *testing.T) { + s := testStateStore(t) + + // Create the first node and service with some checks + testRegisterNode(t, s, 0, "node1") + testRegisterService(t, s, 1, "node1", "service1") + testRegisterCheck(t, s, 2, "node1", "service1", "check1", structs.HealthPassing) + testRegisterCheck(t, s, 3, "node1", "service1", "check2", structs.HealthPassing) + + // Create a second node/service with a different set of checks + testRegisterNode(t, s, 4, "node2") + testRegisterService(t, s, 5, "node2", "service2") + testRegisterCheck(t, s, 6, "node2", "service2", "check3", structs.HealthPassing) + + // Try querying for all checks associated with node1 + idx, checks, err := s.NodeChecks("node1") + if err != nil { + t.Fatalf("err: %s", err) + } + if idx != 3 { + t.Fatalf("bad index: %d", idx) + } + if len(checks) != 2 || checks[0].CheckID != "check1" || checks[1].CheckID != "check2" { + t.Fatalf("bad checks: %#v", checks) + } + + // Try querying for all checks associated with node2 + idx, checks, err = s.NodeChecks("node2") + if err != nil { + t.Fatalf("err: %s", err) + } + if idx != 6 { + t.Fatalf("bad index: %d", idx) + } + if len(checks) != 1 || checks[0].CheckID != "check3" { + t.Fatalf("bad checks: %#v", checks) + } +} + func TestStateStore_ServiceChecks(t *testing.T) { s := testStateStore(t) @@ -531,33 +613,6 @@ func TestStateStore_ServiceChecks(t *testing.T) { } } -func TestStateStore_DeleteCheck(t *testing.T) { - s := testStateStore(t) - - // Register a node and a node-level health check - testRegisterNode(t, s, 1, "node1") - testRegisterCheck(t, s, 2, "node1", "", "check1", structs.HealthPassing) - - // Delete the check - if err := s.DeleteCheck(3, "node1", "check1"); err != nil { - t.Fatalf("err: %s", err) - } - - // Check is gone - _, checks, err := s.NodeChecks("node1") - if err != nil { - t.Fatalf("err: %s", err) - } - if len(checks) != 0 { - t.Fatalf("bad: %#v", checks) - } - - // Index tables were updated - if idx := s.maxIndex("checks"); idx != 3 { - t.Fatalf("bad index: %d", idx) - } -} - func TestStateStore_ChecksInState(t *testing.T) { s := testStateStore(t) @@ -597,6 +652,42 @@ func TestStateStore_ChecksInState(t *testing.T) { } } +func TestStateStore_DeleteCheck(t *testing.T) { + s := testStateStore(t) + + // Register a node and a node-level health check + testRegisterNode(t, s, 1, "node1") + testRegisterCheck(t, s, 2, "node1", "", "check1", structs.HealthPassing) + + // Delete the check + if err := s.DeleteCheck(3, "node1", "check1"); err != nil { + t.Fatalf("err: %s", err) + } + + // Check is gone + _, checks, err := s.NodeChecks("node1") + if err != nil { + t.Fatalf("err: %s", err) + } + if len(checks) != 0 { + t.Fatalf("bad: %#v", checks) + } + + // Index tables were updated + if idx := s.maxIndex("checks"); idx != 3 { + t.Fatalf("bad index: %d", idx) + } + + // Deleting a nonexistent check should be idempotent and not return an + // error + if err := s.DeleteCheck(4, "node1", "check1"); err != nil { + t.Fatalf("err: %s", err) + } + if idx := s.maxIndex("checks"); idx != 3 { + t.Fatalf("bad index: %d", idx) + } +} + func TestStateStore_CheckServiceNodes(t *testing.T) { s := testStateStore(t) @@ -835,9 +926,15 @@ func TestStateStore_NodeInfo_NodeDump(t *testing.T) { } } -func TestStateStore_KVSSet(t *testing.T) { +func TestStateStore_KVSSet_KVSGet(t *testing.T) { s := testStateStore(t) + // Get on an nonexistent key returns nil + result, err := s.KVSGet("foo") + if result != nil || err != nil { + t.Fatalf("expected (nil, nil), got : (%#v, %#v)", result, err) + } + // Write a new K/V entry to the store entry := &structs.DirEntry{ Key: "foo", @@ -848,7 +945,7 @@ func TestStateStore_KVSSet(t *testing.T) { } // Retrieve the K/V entry again - result, err := s.KVSGet("foo") + result, err = s.KVSGet("foo") if err != nil { t.Fatalf("err: %s", err) } @@ -888,44 +985,6 @@ func TestStateStore_KVSSet(t *testing.T) { } } -func TestStateStore_KVSDelete(t *testing.T) { - s := testStateStore(t) - - // Create some KV pairs - testSetKey(t, s, 1, "foo", "foo") - testSetKey(t, s, 2, "foo/bar", "bar") - - // Call a delete on a specific key - if err := s.KVSDelete(3, "foo"); err != nil { - t.Fatalf("err: %s", err) - } - - // The entry was removed from the state store - tx := s.db.Txn(false) - defer tx.Abort() - e, err := tx.First("kvs", "id", "foo") - if err != nil { - t.Fatalf("err: %s", err) - } - if e != nil { - t.Fatalf("expected kvs entry to be deleted, got: %#v", e) - } - - // Try fetching the other keys to ensure they still exist - e, err = tx.First("kvs", "id", "foo/bar") - if err != nil { - t.Fatalf("err: %s", err) - } - if e == nil || string(e.(*structs.DirEntry).Value) != "bar" { - t.Fatalf("bad kvs entry: %#v", e) - } - - // Check that the index table was updated - if idx := s.maxIndex("kvs"); idx != 3 { - t.Fatalf("bad index: %d", idx) - } -} - func TestStateStore_KVSList(t *testing.T) { s := testStateStore(t) @@ -992,6 +1051,7 @@ func TestStateStore_KVSListKeys(t *testing.T) { testSetKey(t, s, 4, "foo/bar/zip", "zip") testSetKey(t, s, 5, "foo/bar/zip/zam", "zam") testSetKey(t, s, 6, "foo/bar/zip/zorp", "zorp") + testSetKey(t, s, 7, "some/other/prefix", "nack") // Query using a prefix and pass a separator idx, keys, err = s.KVSListKeys("foo/bar/", "/") @@ -1013,6 +1073,9 @@ func TestStateStore_KVSListKeys(t *testing.T) { if err != nil { t.Fatalf("err: %s", err) } + if idx != 6 { + t.Fatalf("bad index: %d", idx) + } expect = []string{"foo", "foo/bar", "foo/bar/baz", "foo/bar/zip", "foo/bar/zip/zam", "foo/bar/zip/zorp"} if !reflect.DeepEqual(keys, expect) { @@ -1020,6 +1083,53 @@ func TestStateStore_KVSListKeys(t *testing.T) { } } +func TestStateStore_KVSDelete(t *testing.T) { + s := testStateStore(t) + + // Create some KV pairs + testSetKey(t, s, 1, "foo", "foo") + testSetKey(t, s, 2, "foo/bar", "bar") + + // Call a delete on a specific key + if err := s.KVSDelete(3, "foo"); err != nil { + t.Fatalf("err: %s", err) + } + + // The entry was removed from the state store + tx := s.db.Txn(false) + defer tx.Abort() + e, err := tx.First("kvs", "id", "foo") + if err != nil { + t.Fatalf("err: %s", err) + } + if e != nil { + t.Fatalf("expected kvs entry to be deleted, got: %#v", e) + } + + // Try fetching the other keys to ensure they still exist + e, err = tx.First("kvs", "id", "foo/bar") + if err != nil { + t.Fatalf("err: %s", err) + } + if e == nil || string(e.(*structs.DirEntry).Value) != "bar" { + t.Fatalf("bad kvs entry: %#v", e) + } + + // Check that the index table was updated + if idx := s.maxIndex("kvs"); idx != 3 { + t.Fatalf("bad index: %d", idx) + } + + // Deleting a nonexistent key should be idempotent and note return an + // error + if err := s.KVSDelete(4, "foo"); err != nil { + t.Fatalf("err: %s", err) + } + if idx := s.maxIndex("kvs"); idx != 3 { + t.Fatalf("bad index: %d", idx) + } +} + func TestStateStore_KVSDeleteCAS(t *testing.T) { s := testStateStore(t) @@ -1065,6 +1175,16 @@ func TestStateStore_KVSDeleteCAS(t *testing.T) { if e != nil { t.Fatalf("entry should be deleted") } + + // A delete on a nonexistent key should be idempotent and not return an + // error + ok, err = s.KVSDeleteCAS(5, 2, "bar") + if !ok || err != nil { + t.Fatalf("expected (true, nil), got: (%v, %#v)", ok, err) + } + if idx := s.maxIndex("kvs"); idx != 4 { + t.Fatalf("bad index: %d", idx) + } } func TestStateStore_KVSSetCAS(t *testing.T) { @@ -1114,7 +1234,7 @@ func TestStateStore_KVSSetCAS(t *testing.T) { // Entry was inserted tx = s.db.Txn(false) - if e, err := tx.First("kvs", "id", "foo"); e == nil || err != nil { + if e, err := tx.First("kvs", "id", "foo"); e == nil || err != nil || string(e.(*structs.DirEntry).Value) != "foo" { t.Fatalf("expected kvs to exist, got: (%#v, %#v)", e, err) } tx.Abort() @@ -1124,6 +1244,21 @@ func TestStateStore_KVSSetCAS(t *testing.T) { t.Fatalf("bad index: %d", idx) } + // Doing a CAS with a ModifyIndex of zero when an entry exists does + // not do anything. + entry = &structs.DirEntry{ + Key: "foo", + Value: []byte("foo"), + RaftIndex: structs.RaftIndex{ + CreateIndex: 0, + ModifyIndex: 0, + }, + } + ok, err = s.KVSSetCAS(3, entry) + if ok || err != nil { + t.Fatalf("expected (false, nil), got: (%#v, %#v)", ok, err) + } + // Doing a CAS with a ModifyIndex which does not match the current // index does not do anything. entry = &structs.DirEntry{ @@ -1155,6 +1290,33 @@ func TestStateStore_KVSSetCAS(t *testing.T) { if idx := s.maxIndex("kvs"); idx != 2 { t.Fatalf("bad index: %d", idx) } + + // Doing a CAS with the proper current index should make the + // modification. + entry = &structs.DirEntry{ + Key: "foo", + Value: []byte("bar"), + RaftIndex: structs.RaftIndex{ + CreateIndex: 2, + ModifyIndex: 2, + }, + } + ok, err = s.KVSSetCAS(3, entry) + if !ok || err != nil { + t.Fatalf("expected (true, nil), got: (%#v, %#v)", ok, err) + } + + // Entry was updated + tx = s.db.Txn(false) + if e, err := tx.First("kvs", "id", "foo"); e == nil || err != nil || string(e.(*structs.DirEntry).Value) != "bar" { + t.Fatalf("expected kvs to exist, got: (%#v, %#v)", e, err) + } + tx.Abort() + + // Index was updated + if idx := s.maxIndex("kvs"); idx != 3 { + t.Fatalf("bad index: %d", idx) + } } func TestStateStore_KVSDeleteTree(t *testing.T) { @@ -1207,7 +1369,7 @@ func TestStateStore_KVSDeleteTree(t *testing.T) { } } -func TestStateStore_SessionCreate(t *testing.T) { +func TestStateStore_SessionCreate_GetSession(t *testing.T) { s := testStateStore(t) // GetSession returns nil if the session doesn't exist @@ -1322,7 +1484,7 @@ func TestStateStore_SessionCreate(t *testing.T) { } } -func TestStateStore_ListSessions(t *testing.T) { +func TestStateStore_SessionList(t *testing.T) { s := testStateStore(t) // Listing when no sessions exist returns nil @@ -1478,7 +1640,7 @@ func TestStateStore_SessionDestroy(t *testing.T) { } } -func TestStateStore_ACLSet(t *testing.T) { +func TestStateStore_ACLSet_ACLGet(t *testing.T) { s := testStateStore(t) // Querying ACL's with no results returns nil @@ -1566,45 +1728,6 @@ func TestStateStore_ACLSet(t *testing.T) { } } -func TestStateStore_ACLDelete(t *testing.T) { - s := testStateStore(t) - - // Calling delete on an ACL which doesn't exist returns nil - if err := s.ACLDelete(1, "nope"); err != nil { - t.Fatalf("err: %s", err) - } - - // Index isn't updated if nothing is deleted - if idx := s.maxIndex("acls"); idx != 0 { - t.Fatalf("bad index: %d", idx) - } - - // Insert an ACL - if err := s.ACLSet(1, &structs.ACL{ID: "acl1"}); err != nil { - t.Fatalf("err: %s", err) - } - - // Delete the ACL and check that the index was updated - if err := s.ACLDelete(2, "acl1"); err != nil { - t.Fatalf("err: %s", err) - } - if idx := s.maxIndex("acls"); idx != 2 { - t.Fatalf("bad index: %d", idx) - } - - tx := s.db.Txn(false) - defer tx.Abort() - - // Check that the ACL was really deleted - result, err := tx.First("acls", "id", "acl1") - if err != nil { - t.Fatalf("err: %s", err) - } - if result != nil { - t.Fatalf("expected nil, got: %#v", result) - } -} - func TestStateStore_ACLList(t *testing.T) { s := testStateStore(t) @@ -1652,3 +1775,42 @@ func TestStateStore_ACLList(t *testing.T) { t.Fatalf("bad: %#v", res) } } + +func TestStateStore_ACLDelete(t *testing.T) { + s := testStateStore(t) + + // Calling delete on an ACL which doesn't exist returns nil + if err := s.ACLDelete(1, "nope"); err != nil { + t.Fatalf("err: %s", err) + } + + // Index isn't updated if nothing is deleted + if idx := s.maxIndex("acls"); idx != 0 { + t.Fatalf("bad index: %d", idx) + } + + // Insert an ACL + if err := s.ACLSet(1, &structs.ACL{ID: "acl1"}); err != nil { + t.Fatalf("err: %s", err) + } + + // Delete the ACL and check that the index was updated + if err := s.ACLDelete(2, "acl1"); err != nil { + t.Fatalf("err: %s", err) + } + if idx := s.maxIndex("acls"); idx != 2 { + t.Fatalf("bad index: %d", idx) + } + + tx := s.db.Txn(false) + defer tx.Abort() + + // Check that the ACL was really deleted + result, err := tx.First("acls", "id", "acl1") + if err != nil { + t.Fatalf("err: %s", err) + } + if result != nil { + t.Fatalf("expected nil, got: %#v", result) + } +} diff --git a/consul/state_store.go b/consul/state_store.go index 038ae212bc..5a0855aa80 100644 --- a/consul/state_store.go +++ b/consul/state_store.go @@ -504,7 +504,7 @@ func (s *StateStore) EnsureRegistration(index uint64, req *structs.RegisterReque defer tx.Abort() // Ensure the node - node := structs.Node{req.Node, req.Address} + node := structs.Node{Node: req.Node, Address: req.Address} if err := s.ensureNodeTxn(index, node, tx); err != nil { return err } @@ -578,9 +578,9 @@ func (s *StateStore) Nodes() (uint64, structs.Nodes) { if err != nil { s.logger.Printf("[ERR] consul.state: Error getting nodes: %v", err) } - results := make([]structs.Node, len(res)) + results := make(structs.Nodes, len(res)) for i, r := range res { - results[i] = *r.(*structs.Node) + results[i] = r.(*structs.Node) } return idx, results } @@ -665,7 +665,7 @@ func (s *StateStore) parseNodeServices(tables MDBTables, tx *MDBTxn, name string // Set the address node := res[0].(*structs.Node) - ns.Node = *node + ns.Node = node // Get the services res, err = s.serviceTable.GetTxn(tx, "id", name) @@ -864,7 +864,7 @@ func (s *StateStore) parseServiceNodes(tx *MDBTxn, table *MDBTable, res []interf } srv.Address = nodeRes[0].(*structs.Node).Address - nodes[i] = *srv + nodes[i] = srv } return nodes @@ -1060,8 +1060,8 @@ func (s *StateStore) parseCheckServiceNodes(tx *MDBTxn, res []interface{}, err e checks = append(checks, nodeChecks...) // Setup the node - nodes[i].Node = *nodeRes[0].(*structs.Node) - nodes[i].Service = structs.NodeService{ + nodes[i].Node = nodeRes[0].(*structs.Node) + nodes[i].Service = &structs.NodeService{ ID: srv.ServiceID, Service: srv.ServiceName, Tags: srv.ServiceTags, @@ -2085,9 +2085,9 @@ func (s *StateSnapshot) Nodes() structs.Nodes { s.store.logger.Printf("[ERR] consul.state: Failed to get nodes: %v", err) return nil } - results := make([]structs.Node, len(res)) + results := make(structs.Nodes, len(res)) for i, r := range res { - results[i] = *r.(*structs.Node) + results[i] = r.(*structs.Node) } return results } diff --git a/consul/state_store_test.go b/consul/state_store_test.go index 13a0044ba5..c1501887e7 100644 --- a/consul/state_store_test.go +++ b/consul/state_store_test.go @@ -24,7 +24,12 @@ func TestEnsureRegistration(t *testing.T) { reg := &structs.RegisterRequest{ Node: "foo", Address: "127.0.0.1", - Service: &structs.NodeService{"api", "api", nil, "", 5000, false}, + Service: &structs.NodeService{ + ID: "api", + Service: "api", + Tags: nil, + Address: "", + Port: 5000}, Check: &structs.HealthCheck{ Node: "foo", CheckID: "api", @@ -81,7 +86,7 @@ func TestEnsureNode(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(3, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(3, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } @@ -90,7 +95,7 @@ func TestEnsureNode(t *testing.T) { t.Fatalf("Bad: %v %v %v", idx, found, addr) } - if err := store.EnsureNode(4, structs.Node{"foo", "127.0.0.2"}); err != nil { + if err := store.EnsureNode(4, structs.Node{Node: "foo", Address: "127.0.0.2"}); err != nil { t.Fatalf("err: %v", err) } @@ -107,11 +112,11 @@ func TestGetNodes(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(40, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(40, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureNode(41, structs.Node{"bar", "127.0.0.2"}); err != nil { + if err := store.EnsureNode(41, structs.Node{Node: "bar", Address: "127.0.0.2"}); err != nil { t.Fatalf("err: %v", err) } @@ -141,7 +146,7 @@ func TestGetNodes_Watch_StopWatch(t *testing.T) { store.Watch(store.QueryTables("Nodes"), notify2) store.StopWatch(store.QueryTables("Nodes"), notify2) - if err := store.EnsureNode(40, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(40, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } @@ -165,11 +170,11 @@ func BenchmarkGetNodes(b *testing.B) { } defer store.Close() - if err := store.EnsureNode(100, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(100, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { b.Fatalf("err: %v", err) } - if err := store.EnsureNode(101, structs.Node{"bar", "127.0.0.2"}); err != nil { + if err := store.EnsureNode(101, structs.Node{Node: "bar", Address: "127.0.0.2"}); err != nil { b.Fatalf("err: %v", err) } @@ -185,19 +190,19 @@ func TestEnsureService(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(10, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(10, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(11, "foo", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil { + if err := store.EnsureService(11, "foo", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5001, false}); err != nil { + if err := store.EnsureService(12, "foo", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5001}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(13, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000, false}); err != nil { + if err := store.EnsureService(13, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } @@ -230,19 +235,19 @@ func TestEnsureService_DuplicateNode(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(10, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(10, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(11, "foo", &structs.NodeService{"api1", "api", nil, "", 5000, false}); err != nil { + if err := store.EnsureService(11, "foo", &structs.NodeService{ID: "api1", Service: "api", Tags: nil, Address: "", Port: 5000}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(12, "foo", &structs.NodeService{"api2", "api", nil, "", 5001, false}); err != nil { + if err := store.EnsureService(12, "foo", &structs.NodeService{ID: "api2", Service: "api", Tags: nil, Address: "", Port: 5001}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(13, "foo", &structs.NodeService{"api3", "api", nil, "", 5002, false}); err != nil { + if err := store.EnsureService(13, "foo", &structs.NodeService{ID: "api3", Service: "api", Tags: nil, Address: "", Port: 5002}); err != nil { t.Fatalf("err: %v", err) } @@ -283,11 +288,11 @@ func TestDeleteNodeService(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(11, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(11, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil { + if err := store.EnsureService(12, "foo", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000}); err != nil { t.Fatalf("err: %v", err) } @@ -331,15 +336,15 @@ func TestDeleteNodeService_One(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(11, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(11, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil { + if err := store.EnsureService(12, "foo", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(13, "foo", &structs.NodeService{"api2", "api", nil, "", 5001, false}); err != nil { + if err := store.EnsureService(13, "foo", &structs.NodeService{ID: "api2", Service: "api", Tags: nil, Address: "", Port: 5001}); err != nil { t.Fatalf("err: %v", err) } @@ -368,11 +373,11 @@ func TestDeleteNode(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(20, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(20, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(21, "foo", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil { + if err := store.EnsureService(21, "foo", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000}); err != nil { t.Fatalf("err: %v", err) } @@ -423,23 +428,23 @@ func TestGetServices(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(30, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(30, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureNode(31, structs.Node{"bar", "127.0.0.2"}); err != nil { + if err := store.EnsureNode(31, structs.Node{Node: "bar", Address: "127.0.0.2"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(32, "foo", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil { + if err := store.EnsureService(32, "foo", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(33, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000, false}); err != nil { + if err := store.EnsureService(33, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(34, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000, false}); err != nil { + if err := store.EnsureService(34, "bar", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"slave"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } @@ -473,31 +478,31 @@ func TestServiceNodes(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(10, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(10, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureNode(11, structs.Node{"bar", "127.0.0.2"}); err != nil { + if err := store.EnsureNode(11, structs.Node{Node: "bar", Address: "127.0.0.2"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil { + if err := store.EnsureService(12, "foo", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(13, "bar", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil { + if err := store.EnsureService(13, "bar", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(14, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000, false}); err != nil { + if err := store.EnsureService(14, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(15, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000, false}); err != nil { + if err := store.EnsureService(15, "bar", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"slave"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(16, "bar", &structs.NodeService{"db2", "db", []string{"slave"}, "", 8001, false}); err != nil { + if err := store.EnsureService(16, "bar", &structs.NodeService{ID: "db2", Service: "db", Tags: []string{"slave"}, Address: "", Port: 8001}); err != nil { t.Fatalf("err: %v", err) } @@ -564,23 +569,23 @@ func TestServiceTagNodes(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(15, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(15, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureNode(16, structs.Node{"bar", "127.0.0.2"}); err != nil { + if err := store.EnsureNode(16, structs.Node{Node: "bar", Address: "127.0.0.2"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(17, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000, false}); err != nil { + if err := store.EnsureService(17, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(18, "foo", &structs.NodeService{"db2", "db", []string{"slave"}, "", 8001, false}); err != nil { + if err := store.EnsureService(18, "foo", &structs.NodeService{ID: "db2", Service: "db", Tags: []string{"slave"}, Address: "", Port: 8001}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(19, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000, false}); err != nil { + if err := store.EnsureService(19, "bar", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"slave"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } @@ -612,23 +617,23 @@ func TestServiceTagNodes_MultipleTags(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(15, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(15, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureNode(16, structs.Node{"bar", "127.0.0.2"}); err != nil { + if err := store.EnsureNode(16, structs.Node{Node: "bar", Address: "127.0.0.2"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(17, "foo", &structs.NodeService{"db", "db", []string{"master", "v2"}, "", 8000, false}); err != nil { + if err := store.EnsureService(17, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"master", "v2"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(18, "foo", &structs.NodeService{"db2", "db", []string{"slave", "v2", "dev"}, "", 8001, false}); err != nil { + if err := store.EnsureService(18, "foo", &structs.NodeService{ID: "db2", Service: "db", Tags: []string{"slave", "v2", "dev"}, Address: "", Port: 8001}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(19, "bar", &structs.NodeService{"db", "db", []string{"slave", "v2"}, "", 8000, false}); err != nil { + if err := store.EnsureService(19, "bar", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"slave", "v2"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } @@ -688,23 +693,23 @@ func TestStoreSnapshot(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(8, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(8, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureNode(9, structs.Node{"bar", "127.0.0.2"}); err != nil { + if err := store.EnsureNode(9, structs.Node{Node: "bar", Address: "127.0.0.2"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(10, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000, false}); err != nil { + if err := store.EnsureService(10, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(11, "foo", &structs.NodeService{"db2", "db", []string{"slave"}, "", 8001, false}); err != nil { + if err := store.EnsureService(11, "foo", &structs.NodeService{ID: "db2", Service: "db", Tags: []string{"slave"}, Address: "", Port: 8001}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(12, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000, false}); err != nil { + if err := store.EnsureService(12, "bar", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"slave"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } @@ -889,13 +894,13 @@ func TestStoreSnapshot(t *testing.T) { } // Make some changes! - if err := store.EnsureService(23, "foo", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000, false}); err != nil { + if err := store.EnsureService(23, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"slave"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(24, "bar", &structs.NodeService{"db", "db", []string{"master"}, "", 8000, false}); err != nil { + if err := store.EnsureService(24, "bar", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureNode(25, structs.Node{"baz", "127.0.0.3"}); err != nil { + if err := store.EnsureNode(25, structs.Node{Node: "baz", Address: "127.0.0.3"}); err != nil { t.Fatalf("err: %v", err) } checkAfter := &structs.HealthCheck{ @@ -1016,10 +1021,10 @@ func TestEnsureCheck(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000, false}); err != nil { + if err := store.EnsureService(2, "foo", &structs.NodeService{ID: "db1", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } check := &structs.HealthCheck{ @@ -1112,10 +1117,10 @@ func TestDeleteNodeCheck(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000, false}); err != nil { + if err := store.EnsureService(2, "foo", &structs.NodeService{ID: "db1", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } check := &structs.HealthCheck{ @@ -1162,10 +1167,10 @@ func TestCheckServiceNodes(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000, false}); err != nil { + if err := store.EnsureService(2, "foo", &structs.NodeService{ID: "db1", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } check := &structs.HealthCheck{ @@ -1243,10 +1248,10 @@ func BenchmarkCheckServiceNodes(t *testing.B) { } defer store.Close() - if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000, false}); err != nil { + if err := store.EnsureService(2, "foo", &structs.NodeService{ID: "db1", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } check := &structs.HealthCheck{ @@ -1281,28 +1286,26 @@ func TestSS_Register_Deregister_Query(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } srv := &structs.NodeService{ - "statsite-box-stats", - "statsite-box-stats", - nil, - "", - 0, - false} + ID: "statsite-box-stats", + Service: "statsite-box-stats", + Tags: nil, + Address: "", + Port: 0} if err := store.EnsureService(2, "foo", srv); err != nil { t.Fatalf("err: %v", err) } srv = &structs.NodeService{ - "statsite-share-stats", - "statsite-share-stats", - nil, - "", - 0, - false} + ID: "statsite-share-stats", + Service: "statsite-share-stats", + Tags: nil, + Address: "", + Port: 0} if err := store.EnsureService(3, "foo", srv); err != nil { t.Fatalf("err: %v", err) } @@ -1327,10 +1330,10 @@ func TestNodeInfo(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000, false}); err != nil { + if err := store.EnsureService(2, "foo", &structs.NodeService{ID: "db1", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } check := &structs.HealthCheck{ @@ -1386,16 +1389,16 @@ func TestNodeDump(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000, false}); err != nil { + if err := store.EnsureService(2, "foo", &structs.NodeService{ID: "db1", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureNode(3, structs.Node{"baz", "127.0.0.2"}); err != nil { + if err := store.EnsureNode(3, structs.Node{Node: "baz", Address: "127.0.0.2"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(4, "baz", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000, false}); err != nil { + if err := store.EnsureService(4, "baz", &structs.NodeService{ID: "db1", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { t.Fatalf("err: %v", err) } @@ -1696,10 +1699,10 @@ func TestKVSCheckAndSet(t *testing.T) { // CAS should fail, no entry d := &structs.DirEntry{ - ModifyIndex: 100, - Key: "/foo", - Flags: 42, - Value: []byte("test"), + RaftIndex: structs.RaftIndex{ModifyIndex: 100}, + Key: "/foo", + Flags: 42, + Value: []byte("test"), } ok, err := store.KVSCheckAndSet(1000, d) if err != nil { @@ -2296,7 +2299,7 @@ func TestSessionCreate(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(3, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(3, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } check := &structs.HealthCheck{ @@ -2341,7 +2344,7 @@ func TestSessionCreate_Invalid(t *testing.T) { } // Check not registered - if err := store.EnsureNode(3, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(3, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } if err := store.SessionCreate(1000, session); err.Error() != "Missing check 'bar' registration" { @@ -2370,7 +2373,7 @@ func TestSession_Lookups(t *testing.T) { defer store.Close() // Create a session - if err := store.EnsureNode(3, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(3, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } session := &structs.Session{ @@ -2455,7 +2458,7 @@ func TestSessionInvalidate_CriticalHealthCheck(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(3, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(3, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } check := &structs.HealthCheck{ @@ -2499,7 +2502,7 @@ func TestSessionInvalidate_DeleteHealthCheck(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(3, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(3, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } check := &structs.HealthCheck{ @@ -2542,7 +2545,7 @@ func TestSessionInvalidate_DeleteNode(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(3, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(3, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } @@ -2576,10 +2579,10 @@ func TestSessionInvalidate_DeleteNodeService(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(11, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(11, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } - if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil { + if err := store.EnsureService(12, "foo", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000}); err != nil { t.Fatalf("err: %v", err) } check := &structs.HealthCheck{ @@ -2624,7 +2627,7 @@ func TestKVSLock(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(3, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(3, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } session := &structs.Session{ID: generateUUID(), Node: "foo"} @@ -2697,7 +2700,7 @@ func TestKVSUnlock(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(3, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(3, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } session := &structs.Session{ID: generateUUID(), Node: "foo"} @@ -2754,7 +2757,7 @@ func TestSessionInvalidate_KeyUnlock(t *testing.T) { t.Fatalf("err: %v", err) } defer store.Close() - if err := store.EnsureNode(3, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(3, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } session := &structs.Session{ @@ -2822,7 +2825,7 @@ func TestSessionInvalidate_KeyDelete(t *testing.T) { } defer store.Close() - if err := store.EnsureNode(3, structs.Node{"foo", "127.0.0.1"}); err != nil { + if err := store.EnsureNode(3, structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { t.Fatalf("err: %v", err) } session := &structs.Session{ diff --git a/consul/structs/structs.go b/consul/structs/structs.go index 2d49bb9bda..cfc455e0f8 100644 --- a/consul/structs/structs.go +++ b/consul/structs/structs.go @@ -286,7 +286,7 @@ type HealthCheck struct { } type HealthChecks []*HealthCheck -// CheckServiceNode is used to provide the node, it's service +// CheckServiceNode is used to provide the node, its service // definition, as well as a HealthCheck that is associated type CheckServiceNode struct { Node *Node