mirror of https://github.com/status-im/consul.git
Merge pull request #9881 from hashicorp/dnephin/state-index-service-check-nodes
state: convert services.node and checks.node indexes
This commit is contained in:
commit
9f03e23e44
|
@ -58,21 +58,13 @@ func (s *Snapshot) Nodes() (memdb.ResultIterator, error) {
|
||||||
// Services is used to pull the full list of services for a given node for use
|
// Services is used to pull the full list of services for a given node for use
|
||||||
// during snapshots.
|
// during snapshots.
|
||||||
func (s *Snapshot) Services(node string) (memdb.ResultIterator, error) {
|
func (s *Snapshot) Services(node string) (memdb.ResultIterator, error) {
|
||||||
iter, err := catalogServiceListByNode(s.tx, node, structs.WildcardEnterpriseMeta(), true)
|
return s.tx.Get(tableServices, indexNode, Query{Value: node})
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return iter, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks is used to pull the full list of checks for a given node for use
|
// Checks is used to pull the full list of checks for a given node for use
|
||||||
// during snapshots.
|
// during snapshots.
|
||||||
func (s *Snapshot) Checks(node string) (memdb.ResultIterator, error) {
|
func (s *Snapshot) Checks(node string) (memdb.ResultIterator, error) {
|
||||||
iter, err := catalogListChecksByNode(s.tx, node, structs.WildcardEnterpriseMeta())
|
return s.tx.Get(tableChecks, indexNode, Query{Value: node})
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return iter, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registration is used to make sure a node, service, and check registration is
|
// Registration is used to make sure a node, service, and check registration is
|
||||||
|
@ -509,7 +501,7 @@ func (s *Store) deleteNodeTxn(tx WriteTxn, idx uint64, nodeName string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete all services associated with the node and update the service index.
|
// Delete all services associated with the node and update the service index.
|
||||||
services, err := tx.Get("services", "node", nodeName)
|
services, err := tx.Get(tableServices, indexNode, Query{Value: nodeName})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed service lookup: %s", err)
|
return fmt.Errorf("failed service lookup: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -535,7 +527,7 @@ func (s *Store) deleteNodeTxn(tx WriteTxn, idx uint64, nodeName string) error {
|
||||||
|
|
||||||
// Delete all checks associated with the node. This will invalidate
|
// Delete all checks associated with the node. This will invalidate
|
||||||
// sessions as necessary.
|
// sessions as necessary.
|
||||||
checks, err := tx.Get("checks", "node", nodeName)
|
checks, err := tx.Get(tableChecks, indexNode, Query{Value: nodeName})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed check lookup: %s", err)
|
return fmt.Errorf("failed check lookup: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -1414,7 +1406,7 @@ func (s *Store) EnsureCheck(idx uint64, hc *structs.HealthCheck) error {
|
||||||
|
|
||||||
// updateAllServiceIndexesOfNode updates the Raft index of all the services associated with this node
|
// updateAllServiceIndexesOfNode updates the Raft index of all the services associated with this node
|
||||||
func updateAllServiceIndexesOfNode(tx WriteTxn, idx uint64, nodeID string) error {
|
func updateAllServiceIndexesOfNode(tx WriteTxn, idx uint64, nodeID string) error {
|
||||||
services, err := tx.Get("services", "node", nodeID)
|
services, err := tx.Get(tableServices, indexNode, Query{Value: nodeID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed updating services for node %s: %s", nodeID, err)
|
return fmt.Errorf("failed updating services for node %s: %s", nodeID, err)
|
||||||
}
|
}
|
||||||
|
@ -1589,11 +1581,15 @@ func (s *Store) NodeChecks(ws memdb.WatchSet, nodeName string, entMeta *structs.
|
||||||
tx := s.db.Txn(false)
|
tx := s.db.Txn(false)
|
||||||
defer tx.Abort()
|
defer tx.Abort()
|
||||||
|
|
||||||
|
if entMeta == nil {
|
||||||
|
entMeta = structs.DefaultEnterpriseMeta()
|
||||||
|
}
|
||||||
|
|
||||||
// Get the table index.
|
// Get the table index.
|
||||||
idx := catalogChecksMaxIndex(tx, entMeta)
|
idx := catalogChecksMaxIndex(tx, entMeta)
|
||||||
|
|
||||||
// Return the checks.
|
// Return the checks.
|
||||||
iter, err := catalogListChecksByNode(tx, nodeName, entMeta)
|
iter, err := catalogListChecksByNode(tx, Query{Value: nodeName, EnterpriseMeta: *entMeta})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, fmt.Errorf("failed check lookup: %s", err)
|
return 0, nil, fmt.Errorf("failed check lookup: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -2286,6 +2282,10 @@ func serviceDumpKindTxn(tx ReadTxn, ws memdb.WatchSet, kind structs.ServiceKind,
|
||||||
func parseNodes(tx ReadTxn, ws memdb.WatchSet, idx uint64,
|
func parseNodes(tx ReadTxn, ws memdb.WatchSet, idx uint64,
|
||||||
iter memdb.ResultIterator, entMeta *structs.EnterpriseMeta) (uint64, structs.NodeDump, error) {
|
iter memdb.ResultIterator, entMeta *structs.EnterpriseMeta) (uint64, structs.NodeDump, error) {
|
||||||
|
|
||||||
|
if entMeta == nil {
|
||||||
|
entMeta = structs.DefaultEnterpriseMeta()
|
||||||
|
}
|
||||||
|
|
||||||
// We don't want to track an unlimited number of services, so we pull a
|
// We don't want to track an unlimited number of services, so we pull a
|
||||||
// top-level watch to use as a fallback.
|
// top-level watch to use as a fallback.
|
||||||
allServices, err := tx.Get("services", "id")
|
allServices, err := tx.Get("services", "id")
|
||||||
|
@ -2326,7 +2326,7 @@ func parseNodes(tx ReadTxn, ws memdb.WatchSet, idx uint64,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query the service level checks
|
// Query the service level checks
|
||||||
checks, err := catalogListChecksByNode(tx, node.Node, entMeta)
|
checks, err := catalogListChecksByNode(tx, Query{Value: node.Node, EnterpriseMeta: *entMeta})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, fmt.Errorf("failed node lookup: %s", err)
|
return 0, nil, fmt.Errorf("failed node lookup: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -491,7 +491,7 @@ func getPayloadCheckServiceNode(payload stream.Payload) *structs.CheckServiceNod
|
||||||
// parseCheckServiceNodes but is more efficient since we know they are all on
|
// parseCheckServiceNodes but is more efficient since we know they are all on
|
||||||
// the same node.
|
// the same node.
|
||||||
func newServiceHealthEventsForNode(tx ReadTxn, idx uint64, node string) ([]stream.Event, error) {
|
func newServiceHealthEventsForNode(tx ReadTxn, idx uint64, node string) ([]stream.Event, error) {
|
||||||
services, err := catalogServiceListByNode(tx, node, structs.WildcardEnterpriseMeta(), true)
|
services, err := tx.Get(tableServices, indexNode, Query{Value: node})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -525,7 +525,7 @@ func getNodeAndChecks(tx ReadTxn, node string) (*structs.Node, serviceChecksFunc
|
||||||
}
|
}
|
||||||
n := nodeRaw.(*structs.Node)
|
n := nodeRaw.(*structs.Node)
|
||||||
|
|
||||||
iter, err := catalogListChecksByNode(tx, node, structs.WildcardEnterpriseMeta())
|
iter, err := tx.Get(tableChecks, indexNode, Query{Value: node})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,24 @@ func indexFromNodeQuery(arg interface{}) ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func indexFromNodeIdentity(raw interface{}) ([]byte, error) {
|
||||||
|
n, ok := raw.(interface {
|
||||||
|
NodeIdentity() structs.Identity
|
||||||
|
})
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("unexpected type %T for index, type must provide NodeIdentity()", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
id := n.NodeIdentity()
|
||||||
|
if id.ID == "" {
|
||||||
|
return nil, errMissingValueForIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
var b indexBuilder
|
||||||
|
b.String(strings.ToLower(id.ID))
|
||||||
|
return b.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
func serviceIndexName(name string, _ *structs.EnterpriseMeta) string {
|
func serviceIndexName(name string, _ *structs.EnterpriseMeta) string {
|
||||||
return fmt.Sprintf("service.%s", name)
|
return fmt.Sprintf("service.%s", name)
|
||||||
}
|
}
|
||||||
|
@ -159,7 +177,7 @@ func catalogServiceListByKind(tx ReadTxn, kind structs.ServiceKind, _ *structs.E
|
||||||
}
|
}
|
||||||
|
|
||||||
func catalogServiceListByNode(tx ReadTxn, node string, _ *structs.EnterpriseMeta, _ bool) (memdb.ResultIterator, error) {
|
func catalogServiceListByNode(tx ReadTxn, node string, _ *structs.EnterpriseMeta, _ bool) (memdb.ResultIterator, error) {
|
||||||
return tx.Get("services", "node", node)
|
return tx.Get(tableServices, indexNode, Query{Value: node})
|
||||||
}
|
}
|
||||||
|
|
||||||
func catalogServiceNodeList(tx ReadTxn, name string, index string, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
func catalogServiceNodeList(tx ReadTxn, name string, index string, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
||||||
|
@ -196,8 +214,8 @@ func catalogChecksMaxIndex(tx ReadTxn, _ *structs.EnterpriseMeta) uint64 {
|
||||||
return maxIndexTxn(tx, "checks")
|
return maxIndexTxn(tx, "checks")
|
||||||
}
|
}
|
||||||
|
|
||||||
func catalogListChecksByNode(tx ReadTxn, node string, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
func catalogListChecksByNode(tx ReadTxn, q Query) (memdb.ResultIterator, error) {
|
||||||
return tx.Get("checks", "node", node)
|
return tx.Get(tableChecks, indexNode, q)
|
||||||
}
|
}
|
||||||
|
|
||||||
func catalogListChecksByService(tx ReadTxn, service string, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
func catalogListChecksByService(tx ReadTxn, service string, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
||||||
|
|
|
@ -22,6 +22,21 @@ func testIndexerTableChecks() map[string]indexerTestCase {
|
||||||
expected: []byte("node\x00service\x00"),
|
expected: []byte("node\x00service\x00"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
indexNode: {
|
||||||
|
read: indexValue{
|
||||||
|
source: Query{
|
||||||
|
Value: "NoDe",
|
||||||
|
},
|
||||||
|
expected: []byte("node\x00"),
|
||||||
|
},
|
||||||
|
write: indexValue{
|
||||||
|
source: &structs.HealthCheck{
|
||||||
|
Node: "NoDe",
|
||||||
|
ServiceID: "SeRvIcE",
|
||||||
|
},
|
||||||
|
expected: []byte("node\x00"),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,3 +54,23 @@ func testIndexerTableNodes() map[string]indexerTestCase {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testIndexerTableServices() map[string]indexerTestCase {
|
||||||
|
return map[string]indexerTestCase{
|
||||||
|
indexNode: {
|
||||||
|
read: indexValue{
|
||||||
|
source: Query{
|
||||||
|
Value: "NoDe",
|
||||||
|
},
|
||||||
|
expected: []byte("node\x00"),
|
||||||
|
},
|
||||||
|
write: indexValue{
|
||||||
|
source: &structs.ServiceNode{
|
||||||
|
Node: "NoDe",
|
||||||
|
ServiceID: "SeRvIcE",
|
||||||
|
},
|
||||||
|
expected: []byte("node\x00"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ const (
|
||||||
indexKind = "kind"
|
indexKind = "kind"
|
||||||
indexStatus = "status"
|
indexStatus = "status"
|
||||||
indexNodeService = "node_service"
|
indexNodeService = "node_service"
|
||||||
|
indexNode = "node"
|
||||||
)
|
)
|
||||||
|
|
||||||
// nodesTableSchema returns a new table schema used for storing struct.Node.
|
// nodesTableSchema returns a new table schema used for storing struct.Node.
|
||||||
|
@ -81,13 +82,13 @@ func servicesTableSchema() *memdb.TableSchema {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"node": {
|
indexNode: {
|
||||||
Name: "node",
|
Name: indexNode,
|
||||||
AllowMissing: false,
|
AllowMissing: false,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: &memdb.StringFieldIndex{
|
Indexer: indexerSingle{
|
||||||
Field: "Node",
|
readIndex: readIndex(indexFromNodeQuery),
|
||||||
Lowercase: true,
|
writeIndex: writeIndex(indexFromNodeIdentity),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
indexServiceName: {
|
indexServiceName: {
|
||||||
|
@ -157,13 +158,13 @@ func checksTableSchema() *memdb.TableSchema {
|
||||||
Lowercase: true,
|
Lowercase: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"node": {
|
indexNode: {
|
||||||
Name: "node",
|
Name: indexNode,
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
Unique: false,
|
Unique: false,
|
||||||
Indexer: &memdb.StringFieldIndex{
|
Indexer: indexerSingle{
|
||||||
Field: "Node",
|
readIndex: readIndex(indexFromNodeQuery),
|
||||||
Lowercase: true,
|
writeIndex: writeIndex(indexFromNodeIdentity),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
indexNodeService: {
|
indexNodeService: {
|
||||||
|
|
|
@ -128,8 +128,9 @@ func TestNewDBSchema_Indexers(t *testing.T) {
|
||||||
require.NoError(t, schema.Validate())
|
require.NoError(t, schema.Validate())
|
||||||
|
|
||||||
var testcases = map[string]func() map[string]indexerTestCase{
|
var testcases = map[string]func() map[string]indexerTestCase{
|
||||||
tableChecks: testIndexerTableChecks,
|
tableChecks: testIndexerTableChecks,
|
||||||
tableNodes: testIndexerTableNodes,
|
tableServices: testIndexerTableServices,
|
||||||
|
tableNodes: testIndexerTableNodes,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, table := range schema.Tables {
|
for _, table := range schema.Tables {
|
||||||
|
|
|
@ -50,7 +50,7 @@ table=checks
|
||||||
index=id unique
|
index=id unique
|
||||||
indexer=github.com/hashicorp/go-memdb.CompoundIndex Indexes=[github.com/hashicorp/go-memdb.StringFieldIndex Field=Node Lowercase=true, github.com/hashicorp/go-memdb.StringFieldIndex Field=CheckID Lowercase=true] AllowMissing=false
|
indexer=github.com/hashicorp/go-memdb.CompoundIndex Indexes=[github.com/hashicorp/go-memdb.StringFieldIndex Field=Node Lowercase=true, github.com/hashicorp/go-memdb.StringFieldIndex Field=CheckID Lowercase=true] AllowMissing=false
|
||||||
index=node allow-missing
|
index=node allow-missing
|
||||||
indexer=github.com/hashicorp/go-memdb.StringFieldIndex Field=Node Lowercase=true
|
indexer=github.com/hashicorp/consul/agent/consul/state.indexerSingle readIndex=github.com/hashicorp/consul/agent/consul/state.indexFromNodeQuery writeIndex=github.com/hashicorp/consul/agent/consul/state.indexFromNodeIdentity
|
||||||
index=node_service allow-missing
|
index=node_service allow-missing
|
||||||
indexer=github.com/hashicorp/consul/agent/consul/state.indexerSingle readIndex=github.com/hashicorp/consul/agent/consul/state.indexFromNodeServiceQuery writeIndex=github.com/hashicorp/consul/agent/consul/state.indexNodeServiceFromHealthCheck
|
indexer=github.com/hashicorp/consul/agent/consul/state.indexerSingle readIndex=github.com/hashicorp/consul/agent/consul/state.indexFromNodeServiceQuery writeIndex=github.com/hashicorp/consul/agent/consul/state.indexNodeServiceFromHealthCheck
|
||||||
index=service allow-missing
|
index=service allow-missing
|
||||||
|
@ -154,7 +154,7 @@ table=services
|
||||||
index=kind
|
index=kind
|
||||||
indexer=github.com/hashicorp/consul/agent/consul/state.IndexServiceKind
|
indexer=github.com/hashicorp/consul/agent/consul/state.IndexServiceKind
|
||||||
index=node
|
index=node
|
||||||
indexer=github.com/hashicorp/go-memdb.StringFieldIndex Field=Node Lowercase=true
|
indexer=github.com/hashicorp/consul/agent/consul/state.indexerSingle readIndex=github.com/hashicorp/consul/agent/consul/state.indexFromNodeQuery writeIndex=github.com/hashicorp/consul/agent/consul/state.indexFromNodeIdentity
|
||||||
index=service allow-missing
|
index=service allow-missing
|
||||||
indexer=github.com/hashicorp/go-memdb.StringFieldIndex Field=ServiceName Lowercase=true
|
indexer=github.com/hashicorp/go-memdb.StringFieldIndex Field=ServiceName Lowercase=true
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package structs
|
||||||
|
|
||||||
|
// Identity of some entity (ex: service, node, check).
|
||||||
|
//
|
||||||
|
// TODO: this type should replace ServiceID, ServiceName, and CheckID which all
|
||||||
|
// have roughly identical implementations.
|
||||||
|
type Identity struct {
|
||||||
|
ID string
|
||||||
|
EnterpriseMeta
|
||||||
|
}
|
|
@ -833,6 +833,10 @@ type ServiceNode struct {
|
||||||
RaftIndex `bexpr:"-"`
|
RaftIndex `bexpr:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ServiceNode) NodeIdentity() Identity {
|
||||||
|
return Identity{ID: s.Node}
|
||||||
|
}
|
||||||
|
|
||||||
// PartialClone() returns a clone of the given service node, minus the node-
|
// PartialClone() returns a clone of the given service node, minus the node-
|
||||||
// related fields that get filled in later, Address and TaggedAddresses.
|
// related fields that get filled in later, Address and TaggedAddresses.
|
||||||
func (s *ServiceNode) PartialClone() *ServiceNode {
|
func (s *ServiceNode) PartialClone() *ServiceNode {
|
||||||
|
@ -1402,6 +1406,10 @@ type HealthCheck struct {
|
||||||
RaftIndex `bexpr:"-"`
|
RaftIndex `bexpr:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hc *HealthCheck) NodeIdentity() Identity {
|
||||||
|
return Identity{ID: hc.Node}
|
||||||
|
}
|
||||||
|
|
||||||
func (hc *HealthCheck) CompoundServiceID() ServiceID {
|
func (hc *HealthCheck) CompoundServiceID() ServiceID {
|
||||||
id := hc.ServiceID
|
id := hc.ServiceID
|
||||||
if id == "" {
|
if id == "" {
|
||||||
|
|
Loading…
Reference in New Issue