2017-01-13 19:47:16 +00:00
|
|
|
package state
|
|
|
|
|
|
|
|
import (
|
2020-05-20 16:43:33 +00:00
|
|
|
"errors"
|
2017-01-13 19:47:16 +00:00
|
|
|
"fmt"
|
2021-12-02 23:42:47 +00:00
|
|
|
"net"
|
2020-04-08 18:37:24 +00:00
|
|
|
"reflect"
|
2017-01-13 19:47:16 +00:00
|
|
|
"strings"
|
|
|
|
|
2022-06-24 18:38:39 +00:00
|
|
|
"github.com/hashicorp/go-memdb"
|
2020-09-03 23:38:03 +00:00
|
|
|
"github.com/mitchellh/copystructure"
|
|
|
|
|
2020-10-08 00:35:34 +00:00
|
|
|
"github.com/hashicorp/consul/acl"
|
2022-08-08 17:44:18 +00:00
|
|
|
"github.com/hashicorp/consul/agent/configentry"
|
2017-07-06 10:34:00 +00:00
|
|
|
"github.com/hashicorp/consul/agent/structs"
|
2017-04-19 23:00:11 +00:00
|
|
|
"github.com/hashicorp/consul/api"
|
2020-04-23 23:16:04 +00:00
|
|
|
"github.com/hashicorp/consul/lib"
|
2017-01-13 19:47:16 +00:00
|
|
|
"github.com/hashicorp/consul/types"
|
|
|
|
)
|
|
|
|
|
2022-06-23 15:13:25 +00:00
|
|
|
const (
|
|
|
|
// indexServiceExtinction keeps track of the last raft index when the last instance
|
|
|
|
// of any service was unregistered. This is used by blocking queries on missing services.
|
|
|
|
indexServiceExtinction = "service_last_extinction"
|
|
|
|
|
|
|
|
// indexNodeExtinction keeps track of the last raft index when the last instance
|
|
|
|
// of any node was unregistered. This is used by blocking queries on missing nodes.
|
|
|
|
indexNodeExtinction = "node_last_extinction"
|
|
|
|
)
|
2018-03-09 16:11:39 +00:00
|
|
|
|
2017-02-01 22:20:25 +00:00
|
|
|
const (
|
|
|
|
// minUUIDLookupLen is used as a minimum length of a node name required before
|
|
|
|
// we test to see if the name is actually a UUID and perform an ID-based node
|
|
|
|
// lookup.
|
2017-02-02 20:12:18 +00:00
|
|
|
minUUIDLookupLen = 2
|
2017-02-01 22:20:25 +00:00
|
|
|
)
|
|
|
|
|
2021-12-02 23:42:47 +00:00
|
|
|
var (
|
|
|
|
// startingVirtualIP is the start of the virtual IP range we assign to services.
|
|
|
|
// The effective CIDR range is startingVirtualIP to (startingVirtualIP + virtualIPMaxOffset).
|
|
|
|
startingVirtualIP = net.IP{240, 0, 0, 0}
|
|
|
|
|
|
|
|
virtualIPMaxOffset = net.IP{15, 255, 255, 254}
|
2022-04-20 00:24:21 +00:00
|
|
|
|
|
|
|
ErrNodeNotFound = errors.New("node not found")
|
2021-12-02 23:42:47 +00:00
|
|
|
)
|
|
|
|
|
2017-02-02 20:13:58 +00:00
|
|
|
func resizeNodeLookupKey(s string) string {
|
|
|
|
l := len(s)
|
|
|
|
|
|
|
|
if l%2 != 0 {
|
|
|
|
return s[0 : l-1]
|
|
|
|
}
|
|
|
|
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// Nodes is used to pull the full list of nodes for use during snapshots.
|
2017-04-21 00:46:29 +00:00
|
|
|
func (s *Snapshot) Nodes() (memdb.ResultIterator, error) {
|
2021-02-19 23:18:25 +00:00
|
|
|
iter, err := s.tx.Get(tableNodes, indexID)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return iter, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Services is used to pull the full list of services for a given node for use
|
|
|
|
// during snapshots.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Snapshot) Services(node string, entMeta *acl.EnterpriseMeta, peerName string) (memdb.ResultIterator, error) {
|
2021-08-17 18:29:39 +00:00
|
|
|
// TODO: accept non-pointer value
|
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.NodeEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
|
|
|
return s.tx.Get(tableServices, indexNode, Query{
|
|
|
|
Value: node,
|
|
|
|
EnterpriseMeta: *entMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: peerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Checks is used to pull the full list of checks for a given node for use
|
|
|
|
// during snapshots.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Snapshot) Checks(node string, entMeta *acl.EnterpriseMeta, peerName string) (memdb.ResultIterator, error) {
|
2021-08-17 18:29:39 +00:00
|
|
|
// TODO: accept non-pointer value
|
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.NodeEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
|
|
|
return s.tx.Get(tableChecks, indexNode, Query{
|
|
|
|
Value: node,
|
|
|
|
EnterpriseMeta: *entMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: peerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2021-12-02 23:42:47 +00:00
|
|
|
// ServiceVirtualIPs is used to pull the service virtual IP mappings for use during snapshots.
|
|
|
|
func (s *Snapshot) ServiceVirtualIPs() (memdb.ResultIterator, error) {
|
|
|
|
iter, err := s.tx.Get(tableServiceVirtualIPs, indexID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return iter, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// FreeVirtualIPs is used to pull the freed virtual IPs for use during snapshots.
|
|
|
|
func (s *Snapshot) FreeVirtualIPs() (memdb.ResultIterator, error) {
|
|
|
|
iter, err := s.tx.Get(tableFreeVirtualIPs, indexID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return iter, nil
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// Registration is used to make sure a node, service, and check registration is
|
|
|
|
// performed within a single transaction to avoid race conditions on state
|
|
|
|
// updates.
|
2017-04-21 00:46:29 +00:00
|
|
|
func (s *Restore) Registration(idx uint64, req *structs.RegisterRequest) error {
|
2020-11-11 16:21:42 +00:00
|
|
|
return s.store.ensureRegistrationTxn(s.tx, idx, true, req, true)
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2021-12-02 23:42:47 +00:00
|
|
|
func (s *Restore) ServiceVirtualIP(req ServiceVirtualIP) error {
|
2022-06-29 20:34:58 +00:00
|
|
|
if err := s.tx.Insert(tableServiceVirtualIPs, req); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := updateVirtualIPMaxIndexes(s.tx, req.ModifyIndex, req.Service.ServiceName.PartitionOrDefault(), req.Service.Peer); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
2021-12-02 23:42:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Restore) FreeVirtualIP(req FreeVirtualIP) error {
|
|
|
|
return s.tx.Insert(tableFreeVirtualIPs, req)
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// EnsureRegistration is used to make sure a node, service, and check
|
|
|
|
// registration is performed within a single transaction to avoid race
|
|
|
|
// conditions on state updates.
|
2017-04-21 00:46:29 +00:00
|
|
|
func (s *Store) EnsureRegistration(idx uint64, req *structs.RegisterRequest) error {
|
2020-03-19 13:11:20 +00:00
|
|
|
tx := s.db.WriteTxn(idx)
|
2017-01-13 19:47:16 +00:00
|
|
|
defer tx.Abort()
|
|
|
|
|
2020-11-11 16:21:42 +00:00
|
|
|
if err := s.ensureRegistrationTxn(tx, idx, false, req, false); err != nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-06-02 20:34:56 +00:00
|
|
|
return tx.Commit()
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2021-12-13 17:43:33 +00:00
|
|
|
func (s *Store) ensureCheckIfNodeMatches(
|
|
|
|
tx WriteTxn,
|
|
|
|
idx uint64,
|
|
|
|
preserveIndexes bool,
|
|
|
|
node string,
|
|
|
|
nodePartition string,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
nodePeerName string,
|
2021-12-13 17:43:33 +00:00
|
|
|
check *structs.HealthCheck,
|
|
|
|
) error {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if !strings.EqualFold(check.PeerName, nodePeerName) {
|
|
|
|
return fmt.Errorf("check peer name %q does not match node peer name %q", check.PeerName, nodePeerName)
|
|
|
|
}
|
2022-04-05 21:10:06 +00:00
|
|
|
if !strings.EqualFold(check.Node, node) || !acl.EqualPartitions(nodePartition, check.PartitionOrDefault()) {
|
2018-08-14 16:45:33 +00:00
|
|
|
return fmt.Errorf("check node %q does not match node %q",
|
2021-12-13 17:43:33 +00:00
|
|
|
printNodeName(check.Node, check.PartitionOrDefault()),
|
|
|
|
printNodeName(node, nodePartition),
|
|
|
|
)
|
2018-08-14 16:45:33 +00:00
|
|
|
}
|
2020-08-11 05:52:36 +00:00
|
|
|
if err := s.ensureCheckTxn(tx, idx, preserveIndexes, check); err != nil {
|
2021-12-13 17:43:33 +00:00
|
|
|
return fmt.Errorf("failed inserting check on node %q: %v", printNodeName(check.Node, check.PartitionOrDefault()), err)
|
2018-08-14 16:45:33 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-12-13 17:43:33 +00:00
|
|
|
func printNodeName(nodeName, partition string) string {
|
2022-04-05 21:10:06 +00:00
|
|
|
if acl.IsDefaultPartition(partition) {
|
2021-12-13 17:43:33 +00:00
|
|
|
return nodeName
|
|
|
|
}
|
|
|
|
return partition + "/" + nodeName
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// ensureRegistrationTxn is used to make sure a node, service, and check
|
|
|
|
// registration is performed within a single transaction to avoid race
|
|
|
|
// conditions on state updates.
|
2020-11-11 16:21:42 +00:00
|
|
|
func (s *Store) ensureRegistrationTxn(tx WriteTxn, idx uint64, preserveIndexes bool, req *structs.RegisterRequest, restore bool) error {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := validateRegisterRequestPeerNamesTxn(tx, req, restore); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-11-11 16:21:42 +00:00
|
|
|
if _, err := validateRegisterRequestTxn(tx, req, restore); err != nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-01-20 05:55:57 +00:00
|
|
|
// Create a node structure.
|
2017-01-13 19:47:16 +00:00
|
|
|
node := &structs.Node{
|
2017-01-18 22:26:42 +00:00
|
|
|
ID: req.ID,
|
2017-01-13 19:47:16 +00:00
|
|
|
Node: req.Node,
|
|
|
|
Address: req.Address,
|
2017-04-18 12:02:24 +00:00
|
|
|
Datacenter: req.Datacenter,
|
2021-08-17 18:29:39 +00:00
|
|
|
Partition: req.PartitionOrDefault(),
|
2017-01-13 19:47:16 +00:00
|
|
|
TaggedAddresses: req.TaggedAddresses,
|
|
|
|
Meta: req.NodeMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: req.PeerName,
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
2020-08-11 05:52:36 +00:00
|
|
|
if preserveIndexes {
|
|
|
|
node.CreateIndex = req.CreateIndex
|
|
|
|
node.ModifyIndex = req.ModifyIndex
|
|
|
|
}
|
2017-01-20 05:55:57 +00:00
|
|
|
|
|
|
|
// Since this gets called for all node operations (service and check
|
|
|
|
// updates) and churn on the node itself is basically none after the
|
|
|
|
// node updates itself the first time, it's worth seeing if we need to
|
|
|
|
// modify the node at all so we prevent watch churn and useless writes
|
|
|
|
// and modify index bumps on the node.
|
|
|
|
{
|
2021-08-17 18:29:39 +00:00
|
|
|
existing, err := tx.First(tableNodes, indexID, Query{
|
|
|
|
Value: node.Node,
|
|
|
|
EnterpriseMeta: *node.GetEnterpriseMeta(),
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: node.PeerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-20 05:55:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("node lookup failed: %s", err)
|
|
|
|
}
|
|
|
|
if existing == nil || req.ChangesNode(existing.(*structs.Node)) {
|
2020-08-11 05:52:36 +00:00
|
|
|
if err := s.ensureNodeTxn(tx, idx, preserveIndexes, node); err != nil {
|
2017-01-20 05:55:57 +00:00
|
|
|
return fmt.Errorf("failed inserting node: %s", err)
|
|
|
|
}
|
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2017-01-20 05:55:57 +00:00
|
|
|
// Add the service, if any. We perform a similar check as we do for the
|
|
|
|
// node info above to make sure we actually need to update the service
|
|
|
|
// definition in order to prevent useless churn if nothing has changed.
|
2017-01-13 19:47:16 +00:00
|
|
|
if req.Service != nil {
|
2021-08-17 18:29:39 +00:00
|
|
|
existing, err := tx.First(tableServices, indexID, NodeServiceQuery{
|
|
|
|
EnterpriseMeta: req.Service.EnterpriseMeta,
|
|
|
|
Node: req.Node,
|
|
|
|
Service: req.Service.ID,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: req.PeerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-20 05:55:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed service lookup: %s", err)
|
|
|
|
}
|
|
|
|
if existing == nil || !(existing.(*structs.ServiceNode).ToNodeService()).IsSame(req.Service) {
|
2020-08-11 05:52:36 +00:00
|
|
|
if err := ensureServiceTxn(tx, idx, req.Node, preserveIndexes, req.Service); err != nil {
|
2017-01-20 05:55:57 +00:00
|
|
|
return fmt.Errorf("failed inserting service: %s", err)
|
|
|
|
|
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the checks, if any.
|
|
|
|
if req.Check != nil {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
err := s.ensureCheckIfNodeMatches(tx, idx, preserveIndexes, req.Node, req.PartitionOrDefault(), req.PeerName, req.Check)
|
|
|
|
if err != nil {
|
2018-08-14 16:45:33 +00:00
|
|
|
return err
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, check := range req.Checks {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
err := s.ensureCheckIfNodeMatches(tx, idx, preserveIndexes, req.Node, req.PartitionOrDefault(), req.PeerName, check)
|
|
|
|
if err != nil {
|
2018-08-14 16:45:33 +00:00
|
|
|
return err
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func validateRegisterRequestPeerNamesTxn(_ ReadTxn, args *structs.RegisterRequest, _ bool) error {
|
|
|
|
var (
|
|
|
|
peerNames = make(map[string]struct{})
|
|
|
|
)
|
|
|
|
if args.Service != nil {
|
|
|
|
if args.Service.PeerName == "" {
|
|
|
|
args.Service.PeerName = args.PeerName
|
|
|
|
}
|
|
|
|
|
|
|
|
peerName := args.Service.PeerName
|
|
|
|
// TODO(peering): validate the peering exists (skip check on restore)
|
|
|
|
|
|
|
|
peerNames[peerName] = struct{}{}
|
|
|
|
}
|
|
|
|
|
|
|
|
validateCheck := func(chk *structs.HealthCheck) error {
|
|
|
|
if chk.PeerName == "" {
|
|
|
|
chk.PeerName = args.PeerName
|
|
|
|
}
|
|
|
|
|
|
|
|
peerName := chk.PeerName
|
|
|
|
// TODO(peering): validate the peering exists (skip check on restore)
|
|
|
|
|
|
|
|
peerNames[peerName] = struct{}{}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if args.Check != nil {
|
|
|
|
if err := validateCheck(args.Check); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, chk := range args.Checks {
|
|
|
|
if err := validateCheck(chk); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// TODO(peering): validate the node's peering exists (skip check on restore)
|
|
|
|
peerName := args.PeerName
|
|
|
|
peerNames[peerName] = struct{}{}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(peerNames) > 1 {
|
|
|
|
return fmt.Errorf("Cannot register services and checks for multiple peer names in one registration request")
|
|
|
|
} else if len(peerNames) == 0 {
|
|
|
|
return fmt.Errorf("No peer names are present on the registration request; this makes no sense")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// EnsureNode is used to upsert node registration or modification.
|
2017-04-21 00:46:29 +00:00
|
|
|
func (s *Store) EnsureNode(idx uint64, node *structs.Node) error {
|
2020-03-19 13:11:20 +00:00
|
|
|
tx := s.db.WriteTxn(idx)
|
2017-01-13 19:47:16 +00:00
|
|
|
defer tx.Abort()
|
|
|
|
|
|
|
|
// Call the node upsert
|
2020-08-11 05:52:36 +00:00
|
|
|
if err := s.ensureNodeTxn(tx, idx, false, node); err != nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-06-02 20:34:56 +00:00
|
|
|
return tx.Commit()
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
// ensureNoNodeWithSimilarNameTxn checks that no other node has conflict in its name
|
|
|
|
// If allowClashWithoutID then, getting a conflict on another node without ID will be allowed
|
2020-09-03 23:38:03 +00:00
|
|
|
func ensureNoNodeWithSimilarNameTxn(tx ReadTxn, node *structs.Node, allowClashWithoutID bool) error {
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
// Retrieve all of the nodes
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
PeerName: node.PeerName,
|
|
|
|
EnterpriseMeta: *node.GetEnterpriseMeta(),
|
|
|
|
}
|
|
|
|
enodes, err := tx.Get(tableNodes, indexID+"_prefix", q)
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Cannot lookup all nodes: %s", err)
|
|
|
|
}
|
|
|
|
for nodeIt := enodes.Next(); nodeIt != nil; nodeIt = enodes.Next() {
|
|
|
|
enode := nodeIt.(*structs.Node)
|
|
|
|
if strings.EqualFold(node.Node, enode.Node) && node.ID != enode.ID {
|
2019-03-08 06:42:54 +00:00
|
|
|
// Look up the existing node's Serf health check to see if it's failed.
|
|
|
|
// If it is, the node can be renamed.
|
2021-08-17 18:29:39 +00:00
|
|
|
enodeCheck, err := tx.First(tableChecks, indexID, NodeCheckQuery{
|
|
|
|
EnterpriseMeta: *node.GetEnterpriseMeta(),
|
|
|
|
Node: enode.Node,
|
|
|
|
CheckID: string(structs.SerfCheckID),
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: enode.PeerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2019-03-08 06:42:54 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Cannot get status of node %s: %s", enode.Node, err)
|
|
|
|
}
|
|
|
|
|
2019-03-18 23:15:36 +00:00
|
|
|
// Get the node health. If there's no Serf health check, we consider it safe to rename
|
|
|
|
// the node as it's likely an external node registration not managed by Consul.
|
2019-03-13 23:23:05 +00:00
|
|
|
var nodeHealthy bool
|
|
|
|
if enodeCheck != nil {
|
|
|
|
enodeSerfCheck, ok := enodeCheck.(*structs.HealthCheck)
|
|
|
|
if ok {
|
|
|
|
nodeHealthy = enodeSerfCheck.Status != api.HealthCritical
|
|
|
|
}
|
2019-03-08 06:42:54 +00:00
|
|
|
}
|
|
|
|
|
2019-03-13 23:23:05 +00:00
|
|
|
if !(enode.ID == "" && allowClashWithoutID) && nodeHealthy {
|
2019-08-28 19:57:05 +00:00
|
|
|
return fmt.Errorf("Node name %s is reserved by node %s with name %s (%s)", node.Node, enode.ID, enode.Node, enode.Address)
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-12-03 07:51:18 +00:00
|
|
|
// ensureNodeCASTxn updates a node only if the existing index matches the given index.
|
|
|
|
// Returns a bool indicating if a write happened and any error.
|
2020-09-03 23:38:03 +00:00
|
|
|
func (s *Store) ensureNodeCASTxn(tx WriteTxn, idx uint64, node *structs.Node) (bool, error) {
|
2018-12-03 07:51:18 +00:00
|
|
|
// Retrieve the existing entry.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
existing, err := getNodeTxn(tx, node.Node, node.GetEnterpriseMeta(), node.PeerName)
|
2018-12-03 07:51:18 +00:00
|
|
|
if err != nil {
|
2019-01-09 19:59:23 +00:00
|
|
|
return false, err
|
2018-12-03 07:51:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check if the we should do the set. A ModifyIndex of 0 means that
|
|
|
|
// we are doing a set-if-not-exists.
|
|
|
|
if node.ModifyIndex == 0 && existing != nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
if node.ModifyIndex != 0 && existing == nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
2019-01-09 19:59:23 +00:00
|
|
|
if existing != nil && node.ModifyIndex != 0 && node.ModifyIndex != existing.ModifyIndex {
|
2018-12-03 07:51:18 +00:00
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Perform the update.
|
2020-08-11 05:52:36 +00:00
|
|
|
if err := s.ensureNodeTxn(tx, idx, false, node); err != nil {
|
2018-12-03 07:51:18 +00:00
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// ensureNodeTxn is the inner function called to actually create a node
|
|
|
|
// registration or modify an existing one in the state store. It allows
|
|
|
|
// passing in a memdb transaction so it may be part of a larger txn.
|
2020-09-03 23:38:03 +00:00
|
|
|
func (s *Store) ensureNodeTxn(tx WriteTxn, idx uint64, preserveIndexes bool, node *structs.Node) error {
|
2017-03-27 07:15:21 +00:00
|
|
|
// See if there's an existing node with this UUID, and make sure the
|
|
|
|
// name is the same.
|
|
|
|
var n *structs.Node
|
|
|
|
if node.ID != "" {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
existing, err := getNodeIDTxn(tx, node.ID, node.GetEnterpriseMeta(), node.PeerName)
|
2017-03-27 07:15:21 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("node lookup failed: %s", err)
|
|
|
|
}
|
|
|
|
if existing != nil {
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
n = existing
|
2022-02-24 22:54:47 +00:00
|
|
|
if !strings.EqualFold(n.Node, node.Node) {
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
// Lets first get all nodes and check whether name do match, we do not allow clash on nodes without ID
|
2020-07-10 00:56:43 +00:00
|
|
|
dupNameError := ensureNoNodeWithSimilarNameTxn(tx, node, false)
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
if dupNameError != nil {
|
2019-08-28 19:57:05 +00:00
|
|
|
return fmt.Errorf("Error while renaming Node ID: %q (%s): %s", node.ID, node.Address, dupNameError)
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
}
|
|
|
|
// We are actually renaming a node, remove its reference first
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
err := s.deleteNodeTxn(tx, idx, n.Node, n.GetEnterpriseMeta(), n.PeerName)
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
if err != nil {
|
2022-06-23 15:13:25 +00:00
|
|
|
return fmt.Errorf("Error while renaming Node ID: %q (%s) from %s to %s: %w",
|
|
|
|
node.ID, node.Address, n.Node, node.Node, err)
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// We allow to "steal" another node name that would have no ID
|
|
|
|
// It basically means that we allow upgrading a node without ID and add the ID
|
2020-07-10 00:56:43 +00:00
|
|
|
dupNameError := ensureNoNodeWithSimilarNameTxn(tx, node, true)
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
if dupNameError != nil {
|
|
|
|
return fmt.Errorf("Error while renaming Node ID: %q: %s", node.ID, dupNameError)
|
2017-03-27 07:15:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
// TODO: else Node.ID == "" should be forbidden in future Consul releases
|
|
|
|
// See https://github.com/hashicorp/consul/pull/3983 for context
|
2017-03-27 07:15:21 +00:00
|
|
|
|
|
|
|
// Check for an existing node by name to support nodes with no IDs.
|
|
|
|
if n == nil {
|
2021-08-17 18:29:39 +00:00
|
|
|
existing, err := tx.First(tableNodes, indexID, Query{
|
|
|
|
Value: node.Node,
|
|
|
|
EnterpriseMeta: *node.GetEnterpriseMeta(),
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: node.PeerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-03-27 07:15:21 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("node name lookup failed: %s", err)
|
|
|
|
}
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
|
2017-03-27 07:15:21 +00:00
|
|
|
if existing != nil {
|
|
|
|
n = existing.(*structs.Node)
|
|
|
|
}
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
// WARNING, for compatibility reasons with tests, we do not check
|
|
|
|
// for case insensitive matches, which may lead to DB corruption
|
|
|
|
// See https://github.com/hashicorp/consul/pull/3983 for context
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2017-03-27 07:15:21 +00:00
|
|
|
// Get the indexes.
|
|
|
|
if n != nil {
|
|
|
|
node.CreateIndex = n.CreateIndex
|
2018-10-11 11:42:39 +00:00
|
|
|
node.ModifyIndex = n.ModifyIndex
|
|
|
|
// We do not need to update anything
|
|
|
|
if node.IsSame(n) {
|
|
|
|
return nil
|
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
node.ModifyIndex = idx
|
2020-08-11 05:52:36 +00:00
|
|
|
} else if !preserveIndexes || node.CreateIndex == 0 {
|
|
|
|
// If this isn't a snapshot or there were no saved indexes, set CreateIndex
|
2020-08-11 20:46:12 +00:00
|
|
|
// and ModifyIndex from the given index. Prior to 1.9.0/1.8.3/1.7.7, nodes
|
2020-08-11 05:52:36 +00:00
|
|
|
// were not saved with an index, so this is to avoid ending up with a 0 index
|
|
|
|
// when loading a snapshot from an older version.
|
2017-01-13 19:47:16 +00:00
|
|
|
node.CreateIndex = idx
|
|
|
|
node.ModifyIndex = idx
|
|
|
|
}
|
|
|
|
|
2017-03-27 07:15:21 +00:00
|
|
|
// Insert the node and update the index.
|
2021-08-17 18:29:39 +00:00
|
|
|
return catalogInsertNode(tx, node)
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2017-02-01 22:20:25 +00:00
|
|
|
// GetNode is used to retrieve a node registration by node name ID.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) GetNode(nodeNameOrID string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, *structs.Node, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
2021-08-17 18:29:39 +00:00
|
|
|
// TODO: accept non-pointer value
|
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.NodeEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// Get the table index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogNodesMaxIndex(tx, entMeta, peerName)
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// Retrieve the node from the state store
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
node, err := getNodeTxn(tx, nodeNameOrID, entMeta, peerName)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("node lookup failed: %s", err)
|
|
|
|
}
|
2018-12-12 17:14:02 +00:00
|
|
|
return idx, node, nil
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func getNodeTxn(tx ReadTxn, nodeNameOrID string, entMeta *acl.EnterpriseMeta, peerName string) (*structs.Node, error) {
|
2021-08-17 18:29:39 +00:00
|
|
|
node, err := tx.First(tableNodes, indexID, Query{
|
|
|
|
Value: nodeNameOrID,
|
|
|
|
EnterpriseMeta: *entMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: peerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2018-12-12 17:14:02 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("node lookup failed: %s", err)
|
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
if node != nil {
|
2018-12-12 17:14:02 +00:00
|
|
|
return node.(*structs.Node), nil
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
2018-12-12 17:14:02 +00:00
|
|
|
return nil, nil
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func getNodeIDTxn(tx ReadTxn, id types.NodeID, entMeta *acl.EnterpriseMeta, peerName string) (*structs.Node, error) {
|
2021-08-19 21:17:59 +00:00
|
|
|
node, err := tx.First(tableNodes, indexUUID+"_prefix", Query{
|
|
|
|
Value: string(id),
|
|
|
|
EnterpriseMeta: *entMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: peerName,
|
2021-08-19 21:17:59 +00:00
|
|
|
})
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("node lookup by ID failed: %s", err)
|
|
|
|
}
|
|
|
|
if node != nil {
|
|
|
|
return node.(*structs.Node), nil
|
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2017-02-01 22:20:25 +00:00
|
|
|
// GetNodeID is used to retrieve a node registration by node ID.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) GetNodeID(id types.NodeID, entMeta *acl.EnterpriseMeta, peerName string) (uint64, *structs.Node, error) {
|
2017-02-01 22:20:25 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
2021-08-19 21:17:59 +00:00
|
|
|
// TODO: accept non-pointer value
|
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.NodeEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogNodesMaxIndex(tx, entMeta, peerName)
|
2017-02-01 22:20:25 +00:00
|
|
|
|
|
|
|
// Retrieve the node from the state store
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
node, err := getNodeIDTxn(tx, id, entMeta, peerName)
|
Allow to rename nodes with IDs, will fix #3974 and #4413 (#4415)
* Allow to rename nodes with IDs, will fix #3974 and #4413
This change allow to rename any well behaving recent agent with an
ID to be renamed safely, ie: without taking the name of another one
with case insensitive comparison.
Deprecated behaviour warning
----------------------------
Due to asceding compatibility, it is still possible however to
"take" the name of another name by not providing any ID.
Note that when not providing any ID, it is possible to have 2 nodes
having similar names with case differences, ie: myNode and mynode
which might lead to DB corruption on Consul server side and
lead to server not properly restarting.
See #3983 and #4399 for Context about this change.
Disabling registration of nodes without IDs as specified in #4414
should probably be the way to go eventually.
* Removed the case-insensitive search when adding a node within the else
block since it breaks the test TestAgentAntiEntropy_Services
While the else case is probably legit, it will be fixed with #4414 in
a later release.
* Added again the test in the else to avoid duplicated names, but
enforce this test only for nodes having IDs.
Thus most tests without any ID will work, and allows us fixing
* Added more tests regarding request with/without IDs.
`TestStateStore_EnsureNode` now test registration and renaming with IDs
`TestStateStore_EnsureNodeDeprecated` tests registration without IDs
and tests removing an ID from a node as well as updated a node
without its ID (deprecated behaviour kept for backwards compatibility)
* Do not allow renaming in case of conflict, including when other node has no ID
* Fixed function GetNodeID that was not working due to wrong type when searching node from its ID
Thus, all tests about renaming were not working properly.
Added the full test cas that allowed me to detect it.
* Better error messages, more tests when nodeID is not a valid UUID in GetNodeID()
* Added separate TestStateStore_GetNodeID to test GetNodeID.
More complete test coverage for GetNodeID
* Added new unit test `TestStateStore_ensureNoNodeWithSimilarNameTxn`
Also fixed comments to be clearer after remarks from @banks
* Fixed error message in unit test to match test case
* Use uuid.ParseUUID to parse Node.ID as requested by @mkeeler
2018-08-10 15:30:45 +00:00
|
|
|
return idx, node, err
|
2017-02-01 22:20:25 +00:00
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// Nodes is used to return all of the known nodes.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) Nodes(ws memdb.WatchSet, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.Nodes, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
2021-08-17 18:29:39 +00:00
|
|
|
// TODO: accept non-pointer value
|
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.NodeEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogNodesMaxIndex(tx, entMeta, peerName)
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// Retrieve all of the nodes
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
PeerName: peerName,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
}
|
|
|
|
nodes, err := tx.Get(tableNodes, indexID+"_prefix", q)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed nodes lookup: %s", err)
|
|
|
|
}
|
2017-01-20 07:36:50 +00:00
|
|
|
ws.Add(nodes.WatchCh())
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// Create and return the nodes list.
|
|
|
|
var results structs.Nodes
|
|
|
|
for node := nodes.Next(); node != nil; node = nodes.Next() {
|
|
|
|
results = append(results, node.(*structs.Node))
|
|
|
|
}
|
|
|
|
return idx, results, nil
|
|
|
|
}
|
|
|
|
|
2017-01-14 01:45:34 +00:00
|
|
|
// NodesByMeta is used to return all nodes with the given metadata key/value pairs.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) NodesByMeta(ws memdb.WatchSet, filters map[string]string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.Nodes, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
2021-08-17 18:29:39 +00:00
|
|
|
// TODO: accept non-pointer value
|
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.NodeEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogNodesMaxIndex(tx, entMeta, peerName)
|
2017-01-13 19:47:16 +00:00
|
|
|
|
2021-08-19 21:17:59 +00:00
|
|
|
if len(filters) == 0 {
|
|
|
|
return idx, nil, nil // NodesByMeta is never called with an empty map, but just in case make it return no results.
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retrieve all of the nodes. We'll do a lookup of just ONE KV pair, which
|
|
|
|
// over-matches if multiple pairs are requested, but then in the loop below
|
|
|
|
// we'll finish filtering.
|
|
|
|
var firstKey, firstValue string
|
|
|
|
for firstKey, firstValue = range filters {
|
2017-01-14 01:45:34 +00:00
|
|
|
break
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
2021-08-17 18:29:39 +00:00
|
|
|
|
2021-08-19 21:17:59 +00:00
|
|
|
nodes, err := tx.Get(tableNodes, indexMeta, KeyValueQuery{
|
|
|
|
Key: firstKey,
|
|
|
|
Value: firstValue,
|
|
|
|
EnterpriseMeta: *entMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: peerName,
|
2021-08-19 21:17:59 +00:00
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed nodes lookup: %s", err)
|
|
|
|
}
|
2017-01-20 07:36:50 +00:00
|
|
|
ws.Add(nodes.WatchCh())
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// Create and return the nodes list.
|
|
|
|
var results structs.Nodes
|
|
|
|
for node := nodes.Next(); node != nil; node = nodes.Next() {
|
2017-01-14 01:45:34 +00:00
|
|
|
n := node.(*structs.Node)
|
|
|
|
if len(filters) <= 1 || structs.SatisfiesMetaFilters(n.Meta, filters) {
|
|
|
|
results = append(results, n)
|
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
return idx, results, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteNode is used to delete a given node by its ID.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) DeleteNode(idx uint64, nodeName string, entMeta *acl.EnterpriseMeta, peerName string) error {
|
2020-03-19 13:11:20 +00:00
|
|
|
tx := s.db.WriteTxn(idx)
|
2017-01-13 19:47:16 +00:00
|
|
|
defer tx.Abort()
|
|
|
|
|
2021-08-17 18:29:39 +00:00
|
|
|
// TODO: accept non-pointer value
|
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.NodeEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// Call the node deletion.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := s.deleteNodeTxn(tx, idx, nodeName, entMeta, peerName); err != nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-06-02 20:34:56 +00:00
|
|
|
return tx.Commit()
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2018-12-03 07:51:18 +00:00
|
|
|
// deleteNodeCASTxn is used to try doing a node delete operation with a given
|
|
|
|
// raft index. If the CAS index specified is not equal to the last observed index for
|
|
|
|
// the given check, then the call is a noop, otherwise a normal check delete is invoked.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) deleteNodeCASTxn(tx WriteTxn, idx, cidx uint64, nodeName string, entMeta *acl.EnterpriseMeta, peerName string) (bool, error) {
|
2018-12-03 07:51:18 +00:00
|
|
|
// Look up the node.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
node, err := getNodeTxn(tx, nodeName, entMeta, peerName)
|
2018-12-03 07:51:18 +00:00
|
|
|
if err != nil {
|
2019-01-09 19:59:23 +00:00
|
|
|
return false, err
|
2018-12-03 07:51:18 +00:00
|
|
|
}
|
|
|
|
if node == nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the existing index does not match the provided CAS
|
|
|
|
// index arg, then we shouldn't update anything and can safely
|
|
|
|
// return early here.
|
2019-01-09 19:59:23 +00:00
|
|
|
if node.ModifyIndex != cidx {
|
|
|
|
return false, nil
|
2018-12-03 07:51:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Call the actual deletion if the above passed.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := s.deleteNodeTxn(tx, idx, nodeName, entMeta, peerName); err != nil {
|
2018-12-03 07:51:18 +00:00
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// deleteNodeTxn is the inner method used for removing a node from
|
|
|
|
// the store within a given transaction.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) deleteNodeTxn(tx WriteTxn, idx uint64, nodeName string, entMeta *acl.EnterpriseMeta, peerName string) error {
|
2021-08-17 18:29:39 +00:00
|
|
|
// TODO: accept non-pointer value
|
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// Look up the node.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
nodeRaw, err := tx.First(tableNodes, indexID, Query{
|
2021-08-17 18:29:39 +00:00
|
|
|
Value: nodeName,
|
|
|
|
EnterpriseMeta: *entMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: peerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("node lookup failed: %s", err)
|
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if nodeRaw == nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete all services associated with the node and update the service index.
|
2021-08-17 18:29:39 +00:00
|
|
|
services, err := tx.Get(tableServices, indexNode, Query{
|
|
|
|
Value: nodeName,
|
|
|
|
EnterpriseMeta: *entMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: peerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed service lookup: %s", err)
|
|
|
|
}
|
2019-12-10 02:26:41 +00:00
|
|
|
var deleteServices []*structs.ServiceNode
|
2017-01-13 19:47:16 +00:00
|
|
|
for service := services.Next(); service != nil; service = services.Next() {
|
2018-02-19 17:29:22 +00:00
|
|
|
svc := service.(*structs.ServiceNode)
|
2019-12-10 02:26:41 +00:00
|
|
|
deleteServices = append(deleteServices, svc)
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := catalogUpdateServiceIndexes(tx, idx, svc.ServiceName, &svc.EnterpriseMeta, svc.PeerName); err != nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
return err
|
2019-07-12 21:19:37 +00:00
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := catalogUpdateServiceKindIndexes(tx, idx, svc.ServiceKind, &svc.EnterpriseMeta, svc.PeerName); err != nil {
|
2019-12-19 16:15:37 +00:00
|
|
|
return err
|
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Do the delete in a separate loop so we don't trash the iterator.
|
2019-12-10 02:26:41 +00:00
|
|
|
for _, svc := range deleteServices {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := s.deleteServiceTxn(tx, idx, nodeName, svc.ServiceID, &svc.EnterpriseMeta, svc.PeerName); err != nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete all checks associated with the node. This will invalidate
|
|
|
|
// sessions as necessary.
|
2021-08-17 18:29:39 +00:00
|
|
|
checks, err := tx.Get(tableChecks, indexNode, Query{
|
|
|
|
Value: nodeName,
|
|
|
|
EnterpriseMeta: *entMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: peerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed check lookup: %s", err)
|
|
|
|
}
|
2019-12-10 02:26:41 +00:00
|
|
|
var deleteChecks []*structs.HealthCheck
|
2017-01-13 19:47:16 +00:00
|
|
|
for check := checks.Next(); check != nil; check = checks.Next() {
|
2019-12-10 02:26:41 +00:00
|
|
|
deleteChecks = append(deleteChecks, check.(*structs.HealthCheck))
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Do the delete in a separate loop so we don't trash the iterator.
|
2019-12-10 02:26:41 +00:00
|
|
|
for _, chk := range deleteChecks {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := s.deleteCheckTxn(tx, idx, nodeName, chk.CheckID, &chk.EnterpriseMeta, chk.PeerName); err != nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if peerName == "" {
|
|
|
|
// Delete any coordinates associated with this node.
|
|
|
|
coords, err := tx.Get(tableCoordinates, indexNode, Query{
|
|
|
|
Value: nodeName,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: structs.DefaultPeerKeyword,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed coordinate lookup: %s", err)
|
|
|
|
}
|
|
|
|
var coordsToDelete []*structs.Coordinate
|
|
|
|
for coord := coords.Next(); coord != nil; coord = coords.Next() {
|
|
|
|
coordsToDelete = append(coordsToDelete, coord.(*structs.Coordinate))
|
|
|
|
}
|
|
|
|
for _, coord := range coordsToDelete {
|
|
|
|
if err := deleteCoordinateTxn(tx, idx, coord); err != nil {
|
|
|
|
return fmt.Errorf("failed deleting coordinate: %s", err)
|
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete the node and update the index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := tx.Delete(tableNodes, nodeRaw); err != nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return fmt.Errorf("failed deleting node: %s", err)
|
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
node := nodeRaw.(*structs.Node)
|
|
|
|
if err := catalogUpdateNodesIndexes(tx, idx, entMeta, node.PeerName); err != nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return fmt.Errorf("failed updating index: %s", err)
|
|
|
|
}
|
|
|
|
|
2022-06-23 15:13:25 +00:00
|
|
|
// Clean up node entry from index table
|
|
|
|
if err := tx.Delete(tableIndex, &IndexEntry{Key: nodeIndexName(nodeName, entMeta, node.PeerName)}); err != nil {
|
|
|
|
return fmt.Errorf("failed deleting nodeIndex %q: %w", nodeIndexName(nodeName, entMeta, node.PeerName), err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := catalogUpdateNodeExtinctionIndex(tx, idx, entMeta, node.PeerName); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if peerName == "" {
|
|
|
|
// Invalidate any sessions for this node.
|
|
|
|
toDelete, err := allNodeSessionsTxn(tx, nodeName, entMeta.PartitionOrDefault())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
for _, session := range toDelete {
|
|
|
|
if err := s.deleteSessionTxn(tx, idx, session.ID, &session.EnterpriseMeta); err != nil {
|
|
|
|
return fmt.Errorf("failed to delete session '%s': %v", session.ID, err)
|
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// EnsureService is called to upsert creation of a given NodeService.
|
2017-04-21 00:46:29 +00:00
|
|
|
func (s *Store) EnsureService(idx uint64, node string, svc *structs.NodeService) error {
|
2020-03-19 13:11:20 +00:00
|
|
|
tx := s.db.WriteTxn(idx)
|
2017-01-13 19:47:16 +00:00
|
|
|
defer tx.Abort()
|
|
|
|
|
|
|
|
// Call the service registration upsert
|
2020-08-11 05:52:36 +00:00
|
|
|
if err := ensureServiceTxn(tx, idx, node, false, svc); err != nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-06-02 20:34:56 +00:00
|
|
|
return tx.Commit()
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2020-05-20 16:43:33 +00:00
|
|
|
var errCASCompareFailed = errors.New("compare-and-set: comparison failed")
|
|
|
|
|
2018-12-03 08:41:24 +00:00
|
|
|
// ensureServiceCASTxn updates a service only if the existing index matches the given index.
|
2020-05-20 20:34:14 +00:00
|
|
|
// Returns an error if the write didn't happen and nil if write was successful.
|
2020-09-03 23:38:03 +00:00
|
|
|
func ensureServiceCASTxn(tx WriteTxn, idx uint64, node string, svc *structs.NodeService) error {
|
2018-12-12 09:15:43 +00:00
|
|
|
// Retrieve the existing service.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
existing, err := tx.First(tableServices, indexID,
|
|
|
|
NodeServiceQuery{
|
|
|
|
EnterpriseMeta: svc.EnterpriseMeta,
|
|
|
|
Node: node,
|
|
|
|
Service: svc.ID,
|
|
|
|
PeerName: svc.PeerName,
|
|
|
|
})
|
2018-12-03 08:41:24 +00:00
|
|
|
if err != nil {
|
2020-05-20 16:43:33 +00:00
|
|
|
return fmt.Errorf("failed service lookup: %s", err)
|
2018-12-03 08:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check if the we should do the set. A ModifyIndex of 0 means that
|
|
|
|
// we are doing a set-if-not-exists.
|
|
|
|
if svc.ModifyIndex == 0 && existing != nil {
|
2020-05-20 16:43:33 +00:00
|
|
|
return errCASCompareFailed
|
2018-12-03 08:41:24 +00:00
|
|
|
}
|
|
|
|
if svc.ModifyIndex != 0 && existing == nil {
|
2020-05-20 16:43:33 +00:00
|
|
|
return errCASCompareFailed
|
2018-12-03 08:41:24 +00:00
|
|
|
}
|
2019-06-17 14:41:04 +00:00
|
|
|
e, ok := existing.(*structs.ServiceNode)
|
2018-12-03 08:41:24 +00:00
|
|
|
if ok && svc.ModifyIndex != 0 && svc.ModifyIndex != e.ModifyIndex {
|
2020-05-20 16:43:33 +00:00
|
|
|
return errCASCompareFailed
|
2018-12-03 08:41:24 +00:00
|
|
|
}
|
|
|
|
|
2020-08-11 05:52:36 +00:00
|
|
|
return ensureServiceTxn(tx, idx, node, false, svc)
|
2018-12-03 08:41:24 +00:00
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// ensureServiceTxn is used to upsert a service registration within an
|
|
|
|
// existing memdb transaction.
|
2020-09-03 23:38:03 +00:00
|
|
|
func ensureServiceTxn(tx WriteTxn, idx uint64, node string, preserveIndexes bool, svc *structs.NodeService) error {
|
2017-01-13 19:47:16 +00:00
|
|
|
// Check for existing service
|
2021-08-17 18:29:39 +00:00
|
|
|
existing, err := tx.First(tableServices, indexID, NodeServiceQuery{
|
|
|
|
EnterpriseMeta: svc.EnterpriseMeta,
|
|
|
|
Node: node,
|
|
|
|
Service: svc.ID,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: svc.PeerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed service lookup: %s", err)
|
|
|
|
}
|
|
|
|
|
2020-03-09 20:59:02 +00:00
|
|
|
if err = structs.ValidateServiceMetadata(svc.Kind, svc.Meta, false); err != nil {
|
2018-03-27 20:22:42 +00:00
|
|
|
return fmt.Errorf("Invalid Service Meta for node %s and serviceID %s: %v", node, svc.ID, err)
|
|
|
|
}
|
2020-04-08 18:37:24 +00:00
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if svc.PeerName == "" {
|
2022-05-31 20:20:12 +00:00
|
|
|
// Do not associate non-typical services with gateways or consul services
|
|
|
|
if svc.Kind == structs.ServiceKindTypical && svc.Service != "consul" {
|
|
|
|
// Check if this service is covered by a gateway's wildcard specifier, we force the service kind to a gateway-service here as that take precedence
|
|
|
|
sn := structs.NewServiceName(svc.Service, &svc.EnterpriseMeta)
|
2022-07-28 19:51:01 +00:00
|
|
|
if err = checkGatewayWildcardsAndUpdate(tx, idx, &sn, svc, structs.GatewayServiceKindService); err != nil {
|
2022-05-31 20:20:12 +00:00
|
|
|
return fmt.Errorf("failed updating gateway mapping: %s", err)
|
|
|
|
}
|
|
|
|
if err = checkGatewayAndUpdate(tx, idx, &sn, structs.GatewayServiceKindService); err != nil {
|
|
|
|
return fmt.Errorf("failed updating gateway mapping: %s", err)
|
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
}
|
2022-06-24 18:38:39 +00:00
|
|
|
// Only upsert KindServiceName if service is local
|
|
|
|
if err := upsertKindServiceName(tx, idx, svc.Kind, svc.CompoundServiceName()); err != nil {
|
|
|
|
return fmt.Errorf("failed to persist service name: %v", err)
|
|
|
|
}
|
2021-12-02 00:44:13 +00:00
|
|
|
}
|
2021-12-02 23:42:47 +00:00
|
|
|
|
2020-09-27 18:38:32 +00:00
|
|
|
// Update upstream/downstream mappings if it's a connect service
|
2021-12-02 23:42:47 +00:00
|
|
|
if svc.Kind == structs.ServiceKindConnectProxy || svc.Connect.Native {
|
2020-09-27 18:38:32 +00:00
|
|
|
if err = updateMeshTopology(tx, idx, node, svc, existing); err != nil {
|
|
|
|
return fmt.Errorf("failed updating upstream/downstream association")
|
|
|
|
}
|
2021-12-02 23:42:47 +00:00
|
|
|
|
2022-08-02 16:41:19 +00:00
|
|
|
service := svc.Service
|
|
|
|
if svc.Kind == structs.ServiceKindConnectProxy {
|
|
|
|
service = svc.Proxy.DestinationServiceName
|
|
|
|
}
|
|
|
|
sn := structs.ServiceName{Name: service, EnterpriseMeta: svc.EnterpriseMeta}
|
|
|
|
if err = checkGatewayWildcardsAndUpdate(tx, idx, &sn, svc, structs.GatewayServiceKindService); err != nil {
|
|
|
|
return fmt.Errorf("failed updating gateway mapping: %s", err)
|
|
|
|
}
|
|
|
|
|
2023-02-21 19:59:36 +00:00
|
|
|
if svc.PeerName == "" && sn.Name != "" {
|
|
|
|
if err := upsertKindServiceName(tx, idx, structs.ServiceKindConnectEnabled, sn); err != nil {
|
|
|
|
return fmt.Errorf("failed to persist service name as connect-enabled: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the virtual IP for the service
|
2021-12-02 23:42:47 +00:00
|
|
|
supported, err := virtualIPsSupported(tx, nil)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if supported {
|
2022-06-24 18:38:39 +00:00
|
|
|
psn := structs.PeeredServiceName{Peer: svc.PeerName, ServiceName: sn}
|
2022-06-29 20:34:58 +00:00
|
|
|
vip, err := assignServiceVirtualIP(tx, idx, psn)
|
2021-12-02 23:42:47 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed updating virtual IP: %s", err)
|
|
|
|
}
|
|
|
|
if svc.TaggedAddresses == nil {
|
|
|
|
svc.TaggedAddresses = make(map[string]structs.ServiceAddress)
|
|
|
|
}
|
|
|
|
svc.TaggedAddresses[structs.TaggedAddressVirtualIP] = structs.ServiceAddress{Address: vip, Port: svc.Port}
|
|
|
|
}
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
2020-04-08 18:37:24 +00:00
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if svc.PeerName == "" {
|
|
|
|
// If there's a terminating gateway config entry for this service, populate the tagged addresses
|
|
|
|
// with virtual IP mappings.
|
|
|
|
termGatewayVIPsSupported, err := terminatingGatewayVirtualIPsSupported(tx, nil)
|
2022-01-12 20:08:49 +00:00
|
|
|
if err != nil {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return err
|
2022-01-12 20:08:49 +00:00
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if termGatewayVIPsSupported && svc.Kind == structs.ServiceKindTerminatingGateway {
|
|
|
|
_, conf, err := configEntryTxn(tx, nil, structs.TerminatingGateway, svc.Service, &svc.EnterpriseMeta)
|
2022-01-12 20:08:49 +00:00
|
|
|
if err != nil {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return fmt.Errorf("failed to retrieve terminating gateway config: %s", err)
|
2022-01-12 20:08:49 +00:00
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if conf != nil {
|
|
|
|
termGatewayConf := conf.(*structs.TerminatingGatewayConfigEntry)
|
2022-06-29 20:34:58 +00:00
|
|
|
addrs, err := getTermGatewayVirtualIPs(tx, idx, termGatewayConf.Services, &svc.EnterpriseMeta)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if svc.TaggedAddresses == nil {
|
|
|
|
svc.TaggedAddresses = make(map[string]structs.ServiceAddress)
|
|
|
|
}
|
|
|
|
for key, addr := range addrs {
|
|
|
|
svc.TaggedAddresses[key] = addr
|
|
|
|
}
|
2022-01-12 20:08:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// Create the service node entry and populate the indexes. Note that
|
2017-01-18 22:26:42 +00:00
|
|
|
// conversion doesn't populate any of the node-specific information.
|
|
|
|
// That's always populated when we read from the state store.
|
2017-01-13 19:47:16 +00:00
|
|
|
entry := svc.ToServiceNode(node)
|
|
|
|
// Get the node
|
2021-08-17 18:29:39 +00:00
|
|
|
n, err := tx.First(tableNodes, indexID, Query{
|
|
|
|
Value: node,
|
|
|
|
EnterpriseMeta: svc.EnterpriseMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: svc.PeerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed node lookup: %s", err)
|
|
|
|
}
|
|
|
|
if n == nil {
|
|
|
|
return ErrMissingNode
|
|
|
|
}
|
2018-10-11 11:42:39 +00:00
|
|
|
if existing != nil {
|
|
|
|
serviceNode := existing.(*structs.ServiceNode)
|
|
|
|
entry.CreateIndex = serviceNode.CreateIndex
|
|
|
|
entry.ModifyIndex = serviceNode.ModifyIndex
|
2019-03-06 17:13:28 +00:00
|
|
|
// We cannot return here because: we want to keep existing behavior (ex: failed node lookup -> ErrMissingNode)
|
2018-10-11 11:42:39 +00:00
|
|
|
// It might be modified in future, but it requires changing many unit tests
|
|
|
|
// Enforcing saving the entry also ensures that if we add default values in .ToServiceNode()
|
|
|
|
// those values will be saved even if node is not really modified for a while.
|
|
|
|
if entry.IsSameService(serviceNode) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
2020-08-11 05:52:36 +00:00
|
|
|
if !preserveIndexes {
|
|
|
|
entry.ModifyIndex = idx
|
|
|
|
if existing == nil {
|
|
|
|
entry.CreateIndex = idx
|
|
|
|
}
|
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// Insert the service and update the index
|
2020-07-10 00:56:43 +00:00
|
|
|
return catalogInsertService(tx, entry)
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2021-12-02 23:42:47 +00:00
|
|
|
// assignServiceVirtualIP assigns a virtual IP to the target service and updates
|
|
|
|
// the global virtual IP counter if necessary.
|
2022-06-29 20:34:58 +00:00
|
|
|
func assignServiceVirtualIP(tx WriteTxn, idx uint64, psn structs.PeeredServiceName) (string, error) {
|
2022-06-24 18:38:39 +00:00
|
|
|
serviceVIP, err := tx.First(tableServiceVirtualIPs, indexID, psn)
|
2021-12-02 23:42:47 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("failed service virtual IP lookup: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Service already has a virtual IP assigned, nothing to do.
|
|
|
|
if serviceVIP != nil {
|
|
|
|
sVIP := serviceVIP.(ServiceVirtualIP).IP
|
|
|
|
result, err := addIPOffset(startingVirtualIP, sVIP)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return result.String(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the next available virtual IP, drawing from any freed from deleted services
|
|
|
|
// first and then falling back to the global counter if none are available.
|
|
|
|
latestVIP, err := tx.First(tableFreeVirtualIPs, indexCounterOnly, false)
|
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("failed virtual IP index lookup: %s", err)
|
|
|
|
}
|
|
|
|
if latestVIP == nil {
|
|
|
|
latestVIP, err = tx.First(tableFreeVirtualIPs, indexCounterOnly, true)
|
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("failed virtual IP index lookup: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if latestVIP != nil {
|
|
|
|
if err := tx.Delete(tableFreeVirtualIPs, latestVIP); err != nil {
|
|
|
|
return "", fmt.Errorf("failed updating freed virtual IP table: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var latest FreeVirtualIP
|
|
|
|
if latestVIP == nil {
|
|
|
|
latest = FreeVirtualIP{
|
|
|
|
IP: net.IPv4zero,
|
|
|
|
IsCounter: true,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
latest = latestVIP.(FreeVirtualIP)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Store the next virtual IP from the counter if there aren't any freed IPs to draw from.
|
|
|
|
// Then increment to store the next free virtual IP.
|
|
|
|
newEntry := FreeVirtualIP{
|
|
|
|
IP: latest.IP,
|
|
|
|
IsCounter: latest.IsCounter,
|
|
|
|
}
|
|
|
|
if latest.IsCounter {
|
|
|
|
newEntry.IP = make(net.IP, len(latest.IP))
|
|
|
|
copy(newEntry.IP, latest.IP)
|
|
|
|
for i := len(newEntry.IP) - 1; i >= 0; i-- {
|
|
|
|
newEntry.IP[i]++
|
|
|
|
if newEntry.IP[i] != 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Out of virtual IPs, fail registration.
|
|
|
|
if newEntry.IP.Equal(virtualIPMaxOffset) {
|
|
|
|
return "", fmt.Errorf("cannot allocate any more unique service virtual IPs")
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := tx.Insert(tableFreeVirtualIPs, newEntry); err != nil {
|
|
|
|
return "", fmt.Errorf("failed updating freed virtual IP table: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assignedVIP := ServiceVirtualIP{
|
2022-06-24 18:38:39 +00:00
|
|
|
Service: psn,
|
2021-12-02 23:42:47 +00:00
|
|
|
IP: newEntry.IP,
|
2022-06-29 20:34:58 +00:00
|
|
|
RaftIndex: structs.RaftIndex{
|
|
|
|
ModifyIndex: idx,
|
|
|
|
CreateIndex: idx,
|
|
|
|
},
|
2021-12-02 23:42:47 +00:00
|
|
|
}
|
|
|
|
if err := tx.Insert(tableServiceVirtualIPs, assignedVIP); err != nil {
|
|
|
|
return "", fmt.Errorf("failed inserting service virtual IP entry: %s", err)
|
|
|
|
}
|
2022-06-29 20:34:58 +00:00
|
|
|
if err := updateVirtualIPMaxIndexes(tx, idx, psn.ServiceName.PartitionOrDefault(), psn.Peer); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2021-12-02 23:42:47 +00:00
|
|
|
|
|
|
|
result, err := addIPOffset(startingVirtualIP, assignedVIP.IP)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return result.String(), nil
|
|
|
|
}
|
|
|
|
|
2022-06-29 20:34:58 +00:00
|
|
|
func updateVirtualIPMaxIndexes(txn WriteTxn, idx uint64, partition, peerName string) error {
|
|
|
|
// update per-partition max index
|
|
|
|
if err := indexUpdateMaxTxn(txn, idx, partitionedIndexEntryName(tableServiceVirtualIPs, partition)); err != nil {
|
|
|
|
return fmt.Errorf("failed while updating partitioned index: %w", err)
|
|
|
|
}
|
|
|
|
if peerName != "" {
|
|
|
|
// track a separate max index for imported services
|
|
|
|
if err := indexUpdateMaxTxn(txn, idx, partitionedIndexEntryName(tableServiceVirtualIPs+".imported", partition)); err != nil {
|
|
|
|
return fmt.Errorf("failed while updating partitioned index for imported services: %w", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-12-02 23:42:47 +00:00
|
|
|
func addIPOffset(a, b net.IP) (net.IP, error) {
|
|
|
|
a4 := a.To4()
|
|
|
|
b4 := b.To4()
|
|
|
|
if a4 == nil || b4 == nil {
|
|
|
|
return nil, errors.New("ip is not ipv4")
|
|
|
|
}
|
|
|
|
|
|
|
|
var raw uint64
|
|
|
|
for i := 0; i < 4; i++ {
|
|
|
|
raw = raw<<8 + uint64(a4[i]) + uint64(b4[i])
|
|
|
|
}
|
|
|
|
return net.IPv4(byte(raw>>24), byte(raw>>16), byte(raw>>8), byte(raw)), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func virtualIPsSupported(tx ReadTxn, ws memdb.WatchSet) (bool, error) {
|
|
|
|
_, entry, err := systemMetadataGetTxn(tx, ws, structs.SystemMetadataVirtualIPsEnabled)
|
|
|
|
if err != nil {
|
|
|
|
return false, fmt.Errorf("failed system metadata lookup: %s", err)
|
|
|
|
}
|
|
|
|
if entry == nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return entry.Value != "", nil
|
|
|
|
}
|
|
|
|
|
2022-01-12 20:08:49 +00:00
|
|
|
func terminatingGatewayVirtualIPsSupported(tx ReadTxn, ws memdb.WatchSet) (bool, error) {
|
|
|
|
_, entry, err := systemMetadataGetTxn(tx, ws, structs.SystemMetadataTermGatewayVirtualIPsEnabled)
|
|
|
|
if err != nil {
|
|
|
|
return false, fmt.Errorf("failed system metadata lookup: %s", err)
|
|
|
|
}
|
|
|
|
if entry == nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return entry.Value != "", nil
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// Services returns all services along with a list of associated tags.
|
2022-08-10 21:52:32 +00:00
|
|
|
func (s *Store) Services(ws memdb.WatchSet, entMeta *acl.EnterpriseMeta, peerName string) (uint64, []*structs.ServiceNode, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
|
|
|
// Get the table index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogServicesMaxIndex(tx, entMeta, peerName)
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// List all the services.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
services, err := catalogServiceListNoWildcard(tx, entMeta, peerName)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed querying services: %s", err)
|
|
|
|
}
|
2017-01-20 07:36:50 +00:00
|
|
|
ws.Add(services.WatchCh())
|
2017-01-13 19:47:16 +00:00
|
|
|
|
2022-08-10 21:52:32 +00:00
|
|
|
var result []*structs.ServiceNode
|
2017-01-13 19:47:16 +00:00
|
|
|
for service := services.Next(); service != nil; service = services.Next() {
|
2022-08-10 21:52:32 +00:00
|
|
|
result = append(result, service.(*structs.ServiceNode))
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
2022-08-10 21:52:32 +00:00
|
|
|
return idx, result, nil
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) ServiceList(ws memdb.WatchSet, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.ServiceList, error) {
|
2020-01-24 15:04:58 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return serviceListTxn(tx, ws, entMeta, peerName)
|
2020-04-16 21:00:48 +00:00
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func serviceListTxn(tx ReadTxn, ws memdb.WatchSet, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.ServiceList, error) {
|
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.NodeEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
|
|
|
|
|
|
|
idx := catalogServicesMaxIndex(tx, entMeta, peerName)
|
2020-01-24 15:04:58 +00:00
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
services, err := tx.Get(tableServices, indexID+"_prefix", Query{
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
})
|
2020-01-24 15:04:58 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed querying services: %s", err)
|
|
|
|
}
|
|
|
|
ws.Add(services.WatchCh())
|
|
|
|
|
2020-06-12 14:57:41 +00:00
|
|
|
unique := make(map[structs.ServiceName]struct{})
|
2020-01-24 15:04:58 +00:00
|
|
|
for service := services.Next(); service != nil; service = services.Next() {
|
|
|
|
svc := service.(*structs.ServiceNode)
|
2021-12-02 16:06:39 +00:00
|
|
|
unique[svc.CompoundServiceName()] = struct{}{}
|
2020-01-24 15:04:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
results := make(structs.ServiceList, 0, len(unique))
|
2020-06-16 17:19:31 +00:00
|
|
|
for sn := range unique {
|
2020-06-12 15:34:02 +00:00
|
|
|
results = append(results, structs.ServiceName{Name: sn.Name, EnterpriseMeta: sn.EnterpriseMeta})
|
2020-01-24 15:04:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return idx, results, nil
|
|
|
|
}
|
|
|
|
|
2017-01-14 01:45:34 +00:00
|
|
|
// ServicesByNodeMeta returns all services, filtered by the given node metadata.
|
2022-08-10 21:52:32 +00:00
|
|
|
func (s *Store) ServicesByNodeMeta(ws memdb.WatchSet, filters map[string]string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, []*structs.ServiceNode, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
2021-08-19 21:17:59 +00:00
|
|
|
// TODO: accept non-pointer value
|
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.NodeEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// Get the table index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogServicesMaxIndex(tx, entMeta, peerName)
|
|
|
|
|
|
|
|
if nodeIdx := catalogNodesMaxIndex(tx, entMeta, peerName); nodeIdx > idx {
|
2019-12-10 02:26:41 +00:00
|
|
|
idx = nodeIdx
|
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
|
2021-08-19 21:17:59 +00:00
|
|
|
if len(filters) == 0 {
|
|
|
|
return idx, nil, nil // ServicesByNodeMeta is never called with an empty map, but just in case make it return no results.
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retrieve all of the nodes. We'll do a lookup of just ONE KV pair, which
|
|
|
|
// over-matches if multiple pairs are requested, but then in the loop below
|
|
|
|
// we'll finish filtering.
|
|
|
|
var firstKey, firstValue string
|
|
|
|
for firstKey, firstValue = range filters {
|
2017-01-14 01:45:34 +00:00
|
|
|
break
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
2021-08-19 21:17:59 +00:00
|
|
|
|
|
|
|
nodes, err := tx.Get(tableNodes, indexMeta, KeyValueQuery{
|
|
|
|
Key: firstKey,
|
|
|
|
Value: firstValue,
|
|
|
|
EnterpriseMeta: *entMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: peerName,
|
2021-08-19 21:17:59 +00:00
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed nodes lookup: %s", err)
|
|
|
|
}
|
2017-01-20 07:36:50 +00:00
|
|
|
ws.Add(nodes.WatchCh())
|
|
|
|
|
|
|
|
// We don't want to track an unlimited number of services, so we pull a
|
|
|
|
// top-level watch to use as a fallback.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
allServices, err := catalogServiceListNoWildcard(tx, entMeta, peerName)
|
2017-01-20 07:36:50 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed services lookup: %s", err)
|
|
|
|
}
|
|
|
|
allServicesCh := allServices.WatchCh()
|
2017-01-13 19:47:16 +00:00
|
|
|
|
2022-08-10 21:52:32 +00:00
|
|
|
var result structs.ServiceNodes
|
2017-01-13 19:47:16 +00:00
|
|
|
for node := nodes.Next(); node != nil; node = nodes.Next() {
|
|
|
|
n := node.(*structs.Node)
|
2017-01-14 01:45:34 +00:00
|
|
|
if len(filters) > 1 && !structs.SatisfiesMetaFilters(n.Meta, filters) {
|
|
|
|
continue
|
|
|
|
}
|
2017-01-24 07:37:21 +00:00
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// List all the services on the node
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
services, err := catalogServiceListByNode(tx, n.Node, entMeta, n.PeerName, false)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed querying services: %s", err)
|
|
|
|
}
|
2017-01-20 07:36:50 +00:00
|
|
|
ws.AddWithLimit(watchLimit, services.WatchCh(), allServicesCh)
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
for service := services.Next(); service != nil; service = services.Next() {
|
2022-08-10 21:52:32 +00:00
|
|
|
result = append(result, service.(*structs.ServiceNode))
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-10 21:52:32 +00:00
|
|
|
return idx, result, nil
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2018-02-19 18:30:25 +00:00
|
|
|
// maxIndexForService return the maximum Raft Index for a service
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
// If the index is not set for the service, it will return the missing
|
|
|
|
// service index.
|
|
|
|
// The service_last_extinction is set to the last raft index when a service
|
|
|
|
// was unregistered (or 0 if no services were ever unregistered). This
|
|
|
|
// allows blocking queries to
|
2022-10-21 19:58:06 +00:00
|
|
|
// - return when the last instance of a service is removed
|
|
|
|
// - block until an instance for this service is available, or another
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
// service is unregistered.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func maxIndexForService(tx ReadTxn, serviceName string, serviceExists, checks bool, entMeta *acl.EnterpriseMeta, peerName string) uint64 {
|
|
|
|
idx, _ := maxIndexAndWatchChForService(tx, serviceName, serviceExists, checks, entMeta, peerName)
|
2019-03-15 20:18:48 +00:00
|
|
|
return idx
|
|
|
|
}
|
|
|
|
|
|
|
|
// maxIndexAndWatchChForService return the maximum Raft Index for a service. If
|
|
|
|
// the index is not set for the service, it will return the missing service
|
|
|
|
// index. The service_last_extinction is set to the last raft index when a
|
|
|
|
// service was unregistered (or 0 if no services were ever unregistered). This
|
|
|
|
// allows blocking queries to
|
2022-10-21 19:58:06 +00:00
|
|
|
// - return when the last instance of a service is removed
|
|
|
|
// - block until an instance for this service is available, or another
|
2019-03-15 20:18:48 +00:00
|
|
|
// service is unregistered.
|
|
|
|
//
|
|
|
|
// It also _may_ return a watch chan to add to a WatchSet. It will only return
|
|
|
|
// one if the service exists, and has a service index. If it doesn't then nil is
|
|
|
|
// returned for the chan. This allows for blocking watchers to _only_ watch this
|
|
|
|
// one chan in the common case, falling back to watching all touched MemDB
|
|
|
|
// indexes in more complicated cases.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func maxIndexAndWatchChForService(tx ReadTxn, serviceName string, serviceExists, checks bool, entMeta *acl.EnterpriseMeta, peerName string) (uint64, <-chan struct{}) {
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
if !serviceExists {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
res, err := catalogServiceLastExtinctionIndex(tx, entMeta, peerName)
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
if missingIdx, ok := res.(*IndexEntry); ok && err == nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
// Note safe to only watch the extinction index as it's not updated when new instances come along so return nil watchCh
|
2019-03-15 20:18:48 +00:00
|
|
|
return missingIdx.Value, nil
|
2018-02-19 17:29:22 +00:00
|
|
|
}
|
|
|
|
}
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
ch, res, err := catalogServiceMaxIndex(tx, serviceName, entMeta, peerName)
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
if idx, ok := res.(*IndexEntry); ok && err == nil {
|
2019-03-15 20:18:48 +00:00
|
|
|
return idx.Value, ch
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return catalogMaxIndex(tx, entMeta, peerName, checks), nil
|
2018-02-19 17:29:22 +00:00
|
|
|
}
|
|
|
|
|
2020-04-29 22:52:27 +00:00
|
|
|
// Wrapper for maxIndexAndWatchChForService that operates on a list of ServiceNodes
|
2020-09-03 23:38:03 +00:00
|
|
|
func maxIndexAndWatchChsForServiceNodes(tx ReadTxn,
|
2020-05-08 15:44:34 +00:00
|
|
|
nodes structs.ServiceNodes, watchChecks bool) (uint64, []<-chan struct{}) {
|
2020-04-29 22:52:27 +00:00
|
|
|
|
|
|
|
var watchChans []<-chan struct{}
|
|
|
|
var maxIdx uint64
|
|
|
|
|
2020-06-12 14:57:41 +00:00
|
|
|
seen := make(map[structs.ServiceName]bool)
|
2020-04-29 22:52:27 +00:00
|
|
|
for i := 0; i < len(nodes); i++ {
|
2020-06-12 14:57:41 +00:00
|
|
|
sn := structs.NewServiceName(nodes[i].ServiceName, &nodes[i].EnterpriseMeta)
|
|
|
|
if ok := seen[sn]; !ok {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx, svcCh := maxIndexAndWatchChForService(tx, sn.Name, true, watchChecks, &sn.EnterpriseMeta, nodes[i].PeerName)
|
2020-04-29 22:52:27 +00:00
|
|
|
if idx > maxIdx {
|
|
|
|
maxIdx = idx
|
|
|
|
}
|
|
|
|
if svcCh != nil {
|
|
|
|
watchChans = append(watchChans, svcCh)
|
|
|
|
}
|
2020-06-12 14:57:41 +00:00
|
|
|
seen[sn] = true
|
2020-04-29 22:52:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return maxIdx, watchChans
|
|
|
|
}
|
|
|
|
|
2018-03-09 18:01:42 +00:00
|
|
|
// ConnectServiceNodes returns the nodes associated with a Connect
|
|
|
|
// compatible destination for the given service name. This will include
|
|
|
|
// both proxies and native integrations.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) ConnectServiceNodes(ws memdb.WatchSet, serviceName string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.ServiceNodes, error) {
|
2021-01-20 20:10:48 +00:00
|
|
|
tx := s.db.ReadTxn()
|
|
|
|
defer tx.Abort()
|
2021-03-26 22:48:55 +00:00
|
|
|
|
|
|
|
// TODO: accept non-pointer value
|
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-03-26 22:48:55 +00:00
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
Value: serviceName,
|
|
|
|
PeerName: peerName,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
}
|
2021-03-26 22:48:55 +00:00
|
|
|
return serviceNodesTxn(tx, ws, indexConnect, q)
|
2018-03-09 18:01:42 +00:00
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// ServiceNodes returns the nodes associated with a given service name.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) ServiceNodes(ws memdb.WatchSet, serviceName string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.ServiceNodes, error) {
|
2021-01-20 20:10:48 +00:00
|
|
|
tx := s.db.ReadTxn()
|
2017-01-13 19:47:16 +00:00
|
|
|
defer tx.Abort()
|
|
|
|
|
2021-03-26 22:48:55 +00:00
|
|
|
// TODO: accept non-pointer value
|
2021-03-26 21:21:38 +00:00
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-03-26 21:21:38 +00:00
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
Value: serviceName,
|
|
|
|
PeerName: peerName,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
}
|
2021-03-26 22:48:55 +00:00
|
|
|
return serviceNodesTxn(tx, ws, indexService, q)
|
|
|
|
}
|
|
|
|
|
|
|
|
func serviceNodesTxn(tx ReadTxn, ws memdb.WatchSet, index string, q Query) (uint64, structs.ServiceNodes, error) {
|
|
|
|
connect := index == indexConnect
|
|
|
|
serviceName := q.Value
|
2021-03-26 21:21:38 +00:00
|
|
|
services, err := tx.Get(tableServices, index, q)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed service lookup: %s", err)
|
|
|
|
}
|
2017-01-20 07:36:50 +00:00
|
|
|
ws.Add(services.WatchCh())
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
var results structs.ServiceNodes
|
|
|
|
for service := services.Next(); service != nil; service = services.Next() {
|
|
|
|
results = append(results, service.(*structs.ServiceNode))
|
|
|
|
}
|
|
|
|
|
2020-04-08 18:37:24 +00:00
|
|
|
// If we are querying for Connect nodes, the associated proxy might be a gateway.
|
|
|
|
// Gateways are tracked in a separate table, and we append them to the result set.
|
|
|
|
// We append rather than replace since it allows users to migrate a service
|
|
|
|
// to the mesh with a mix of sidecars and gateways until all its instances have a sidecar.
|
2020-04-27 22:25:37 +00:00
|
|
|
var idx uint64
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if connect && q.PeerName == "" {
|
2020-04-08 18:37:24 +00:00
|
|
|
// Look up gateway nodes associated with the service
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
gwIdx, nodes, err := serviceGatewayNodes(tx, ws, serviceName, structs.ServiceKindTerminatingGateway, &q.EnterpriseMeta, structs.DefaultPeerKeyword)
|
2020-04-08 18:37:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed gateway nodes lookup: %v", err)
|
|
|
|
}
|
2020-04-27 22:25:37 +00:00
|
|
|
if idx < gwIdx {
|
|
|
|
idx = gwIdx
|
|
|
|
}
|
2020-04-16 21:00:48 +00:00
|
|
|
|
2020-04-29 22:52:27 +00:00
|
|
|
// Watch for index changes to the gateway nodes
|
2020-07-10 00:56:43 +00:00
|
|
|
svcIdx, chans := maxIndexAndWatchChsForServiceNodes(tx, nodes, false)
|
2020-04-29 22:52:27 +00:00
|
|
|
if svcIdx > idx {
|
|
|
|
idx = svcIdx
|
|
|
|
}
|
|
|
|
for _, ch := range chans {
|
2020-04-16 21:00:48 +00:00
|
|
|
ws.Add(ch)
|
|
|
|
}
|
2020-04-29 22:52:27 +00:00
|
|
|
|
2020-04-08 18:37:24 +00:00
|
|
|
for i := 0; i < len(nodes); i++ {
|
|
|
|
results = append(results, nodes[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-24 07:37:21 +00:00
|
|
|
// Fill in the node details.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
results, err = parseServiceNodes(tx, ws, results, &q.EnterpriseMeta, q.PeerName)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed parsing service nodes: %s", err)
|
|
|
|
}
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
|
|
|
|
// Get the table index.
|
2020-05-08 15:44:34 +00:00
|
|
|
// TODO (gateways) (freddy) Why do we always consider the main service index here?
|
|
|
|
// This doesn't seem to make sense for Connect when there's more than 1 result
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
svcIdx := maxIndexForService(tx, serviceName, len(results) > 0, false, &q.EnterpriseMeta, q.PeerName)
|
2020-04-27 22:25:37 +00:00
|
|
|
if idx < svcIdx {
|
|
|
|
idx = svcIdx
|
|
|
|
}
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
return idx, results, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ServiceTagNodes returns the nodes associated with a given service, filtering
|
2018-10-11 11:50:05 +00:00
|
|
|
// out services that don't contain the given tags.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) ServiceTagNodes(ws memdb.WatchSet, service string, tags []string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.ServiceNodes, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
2021-03-26 21:21:38 +00:00
|
|
|
// TODO: accept non-pointer value
|
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-03-26 21:21:38 +00:00
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
services, err := tx.Get(tableServices, indexService, Query{
|
|
|
|
Value: service,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed service lookup: %s", err)
|
|
|
|
}
|
2017-01-20 07:36:50 +00:00
|
|
|
ws.Add(services.WatchCh())
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// Gather all the services and apply the tag filter.
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
serviceExists := false
|
2017-01-13 19:47:16 +00:00
|
|
|
var results structs.ServiceNodes
|
|
|
|
for service := services.Next(); service != nil; service = services.Next() {
|
|
|
|
svc := service.(*structs.ServiceNode)
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
serviceExists = true
|
2018-10-11 11:50:05 +00:00
|
|
|
if !serviceTagsFilter(svc, tags) {
|
2017-01-13 19:47:16 +00:00
|
|
|
results = append(results, svc)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-24 07:37:21 +00:00
|
|
|
// Fill in the node details.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
results, err = parseServiceNodes(tx, ws, results, entMeta, peerName)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed parsing service nodes: %s", err)
|
|
|
|
}
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
// Get the table index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := maxIndexForService(tx, service, serviceExists, false, entMeta, peerName)
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
return idx, results, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// serviceTagFilter returns true (should filter) if the given service node
|
|
|
|
// doesn't contain the given tag.
|
|
|
|
func serviceTagFilter(sn *structs.ServiceNode, tag string) bool {
|
|
|
|
tag = strings.ToLower(tag)
|
|
|
|
|
|
|
|
// Look for the lower cased version of the tag.
|
|
|
|
for _, t := range sn.ServiceTags {
|
|
|
|
if strings.ToLower(t) == tag {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we didn't hit the tag above then we should filter.
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2018-10-11 11:50:05 +00:00
|
|
|
// serviceTagsFilter returns true (should filter) if the given service node
|
|
|
|
// doesn't contain the given set of tags.
|
|
|
|
func serviceTagsFilter(sn *structs.ServiceNode, tags []string) bool {
|
|
|
|
for _, tag := range tags {
|
|
|
|
if serviceTagFilter(sn, tag) {
|
|
|
|
// If any one of the expected tags was not found, filter the service
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If all tags were found, don't filter the service
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2018-05-03 20:54:14 +00:00
|
|
|
// ServiceAddressNodes returns the nodes associated with a given service, filtering
|
|
|
|
// out services that don't match the given serviceAddress
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) ServiceAddressNodes(ws memdb.WatchSet, address string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.ServiceNodes, error) {
|
2018-05-03 20:54:14 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
|
|
|
// List all the services.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
}
|
|
|
|
services, err := tx.Get(tableServices, indexID+"_prefix", q)
|
2018-05-03 20:54:14 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed service lookup: %s", err)
|
|
|
|
}
|
|
|
|
ws.Add(services.WatchCh())
|
|
|
|
|
|
|
|
// Gather all the services and apply the tag filter.
|
|
|
|
var results structs.ServiceNodes
|
|
|
|
for service := services.Next(); service != nil; service = services.Next() {
|
|
|
|
svc := service.(*structs.ServiceNode)
|
|
|
|
if svc.ServiceAddress == address {
|
|
|
|
results = append(results, svc)
|
2019-06-21 17:16:17 +00:00
|
|
|
} else {
|
|
|
|
for _, addr := range svc.ServiceTaggedAddresses {
|
|
|
|
if addr.Address == address {
|
|
|
|
results = append(results, svc)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2018-05-03 20:54:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fill in the node details.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
results, err = parseServiceNodes(tx, ws, results, entMeta, peerName)
|
2018-05-03 20:54:14 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed parsing service nodes: %s", err)
|
|
|
|
}
|
|
|
|
return 0, results, nil
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// parseServiceNodes iterates over a services query and fills in the node details,
|
|
|
|
// returning a ServiceNodes slice.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func parseServiceNodes(tx ReadTxn, ws memdb.WatchSet, services structs.ServiceNodes, entMeta *acl.EnterpriseMeta, peerName string) (structs.ServiceNodes, error) {
|
2017-01-20 07:36:50 +00:00
|
|
|
// We don't want to track an unlimited number of nodes, so we pull a
|
|
|
|
// top-level watch to use as a fallback.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
}
|
|
|
|
allNodes, err := tx.Get(tableNodes, indexID+"_prefix", q)
|
2017-01-20 07:36:50 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed nodes lookup: %s", err)
|
|
|
|
}
|
|
|
|
allNodesCh := allNodes.WatchCh()
|
|
|
|
|
|
|
|
// Fill in the node data for each service instance.
|
2017-01-13 19:47:16 +00:00
|
|
|
var results structs.ServiceNodes
|
|
|
|
for _, sn := range services {
|
|
|
|
// Note that we have to clone here because we don't want to
|
|
|
|
// modify the node-related fields on the object in the database,
|
|
|
|
// which is what we are referencing.
|
|
|
|
s := sn.PartialClone()
|
|
|
|
|
|
|
|
// Grab the corresponding node record.
|
2021-08-17 18:29:39 +00:00
|
|
|
watchCh, n, err := tx.FirstWatch(tableNodes, indexID, Query{
|
|
|
|
Value: sn.Node,
|
|
|
|
EnterpriseMeta: sn.EnterpriseMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: sn.PeerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed node lookup: %s", err)
|
|
|
|
}
|
2017-01-20 07:36:50 +00:00
|
|
|
ws.AddWithLimit(watchLimit, watchCh, allNodesCh)
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// Populate the node-related fields. The tagged addresses may be
|
|
|
|
// used by agents to perform address translation if they are
|
|
|
|
// configured to do that.
|
|
|
|
node := n.(*structs.Node)
|
2017-01-18 22:26:42 +00:00
|
|
|
s.ID = node.ID
|
2017-01-13 19:47:16 +00:00
|
|
|
s.Address = node.Address
|
2017-04-18 12:02:24 +00:00
|
|
|
s.Datacenter = node.Datacenter
|
2017-01-13 19:47:16 +00:00
|
|
|
s.TaggedAddresses = node.TaggedAddresses
|
2021-08-17 18:29:39 +00:00
|
|
|
s.EnterpriseMeta.Merge(node.GetEnterpriseMeta())
|
2017-01-13 19:47:16 +00:00
|
|
|
s.NodeMeta = node.Meta
|
|
|
|
|
|
|
|
results = append(results, s)
|
|
|
|
}
|
|
|
|
return results, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// NodeService is used to retrieve a specific service associated with the given
|
|
|
|
// node.
|
2022-05-27 11:38:52 +00:00
|
|
|
func (s *Store) NodeService(ws memdb.WatchSet, nodeName string, serviceID string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, *structs.NodeService, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
|
|
|
// Get the table index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogServicesMaxIndex(tx, entMeta, peerName)
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// Query the service
|
2022-05-27 11:38:52 +00:00
|
|
|
service, err := getNodeServiceTxn(tx, ws, nodeName, serviceID, entMeta, peerName)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
2017-01-18 22:26:42 +00:00
|
|
|
return 0, nil, fmt.Errorf("failed querying service for node %q: %s", nodeName, err)
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2018-12-03 08:41:24 +00:00
|
|
|
return idx, service, nil
|
|
|
|
}
|
|
|
|
|
2022-05-27 11:38:52 +00:00
|
|
|
func getNodeServiceTxn(tx ReadTxn, ws memdb.WatchSet, nodeName, serviceID string, entMeta *acl.EnterpriseMeta, peerName string) (*structs.NodeService, error) {
|
|
|
|
sn, err := getServiceNodeTxn(tx, ws, nodeName, serviceID, entMeta, peerName)
|
2022-04-20 00:24:21 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if sn != nil {
|
|
|
|
return sn.ToNodeService(), nil
|
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2022-05-27 11:38:52 +00:00
|
|
|
func getServiceNodeTxn(tx ReadTxn, ws memdb.WatchSet, nodeName, serviceID string, entMeta *acl.EnterpriseMeta, peerName string) (*structs.ServiceNode, error) {
|
2021-02-12 18:39:38 +00:00
|
|
|
// TODO: pass non-pointer type for ent meta
|
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-02-12 18:39:38 +00:00
|
|
|
}
|
|
|
|
|
2018-12-03 08:41:24 +00:00
|
|
|
// Query the service
|
2022-05-27 11:38:52 +00:00
|
|
|
watch, service, err := tx.FirstWatch(tableServices, indexID, NodeServiceQuery{
|
2021-08-17 18:29:39 +00:00
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
Node: nodeName,
|
|
|
|
Service: serviceID,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: peerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2018-12-03 08:41:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed querying service for node %q: %s", nodeName, err)
|
|
|
|
}
|
2022-05-27 11:38:52 +00:00
|
|
|
ws.Add(watch)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
if service != nil {
|
2022-04-20 00:24:21 +00:00
|
|
|
return service.(*structs.ServiceNode), nil
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
|
2018-12-03 08:41:24 +00:00
|
|
|
return nil, nil
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2022-04-20 00:24:21 +00:00
|
|
|
// ServiceNode is used to retrieve a specific service by service ID and node ID or name.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) ServiceNode(nodeID, nodeName, serviceID string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, *structs.ServiceNode, error) {
|
2022-04-20 00:24:21 +00:00
|
|
|
var (
|
|
|
|
node *structs.Node
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
if nodeID != "" {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
_, node, err = s.GetNodeID(types.NodeID(nodeID), entMeta, peerName)
|
2022-04-20 00:24:21 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("Failure looking up node by ID %s: %w", nodeID, err)
|
|
|
|
}
|
|
|
|
} else if nodeName != "" {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
_, node, err = s.GetNode(nodeName, entMeta, peerName)
|
2022-04-20 00:24:21 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("Failure looking up node by name %s: %w", nodeName, err)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 0, nil, fmt.Errorf("Node ID or name required to lookup the service")
|
|
|
|
}
|
|
|
|
if node == nil {
|
|
|
|
return 0, nil, ErrNodeNotFound
|
|
|
|
}
|
|
|
|
|
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
|
|
|
// Get the table index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogServicesMaxIndex(tx, entMeta, peerName)
|
2022-04-20 00:24:21 +00:00
|
|
|
|
|
|
|
// Query the service
|
2022-05-27 11:38:52 +00:00
|
|
|
service, err := getServiceNodeTxn(tx, nil, node.Node, serviceID, entMeta, peerName)
|
2022-04-20 00:24:21 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed querying service for node %q: %w", node.Node, err)
|
|
|
|
}
|
2022-08-24 11:03:15 +00:00
|
|
|
if service != nil {
|
|
|
|
service.ID = node.ID
|
|
|
|
}
|
2022-04-20 00:24:21 +00:00
|
|
|
|
|
|
|
return idx, service, nil
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) nodeServices(ws memdb.WatchSet, nodeNameOrID string, entMeta *acl.EnterpriseMeta, peerName string, allowWildcard bool) (bool, uint64, *structs.Node, memdb.ResultIterator, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
2021-08-17 18:29:39 +00:00
|
|
|
// TODO: accept non-pointer value for entMeta
|
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
|
|
|
|
2017-02-01 22:20:25 +00:00
|
|
|
// Query the node by node name
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
watchCh, n, err := tx.FirstWatch(tableNodes, indexID, Query{
|
|
|
|
Value: nodeNameOrID,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
return true, 0, nil, nil, fmt.Errorf("node lookup failed: %s", err)
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
2017-02-01 22:20:25 +00:00
|
|
|
|
2017-02-01 23:18:00 +00:00
|
|
|
if n != nil {
|
|
|
|
ws.Add(watchCh)
|
|
|
|
} else {
|
|
|
|
if len(nodeNameOrID) < minUUIDLookupLen {
|
2017-02-01 22:20:25 +00:00
|
|
|
ws.Add(watchCh)
|
2019-12-10 02:26:41 +00:00
|
|
|
return true, 0, nil, nil, nil
|
2017-02-01 22:20:25 +00:00
|
|
|
}
|
2017-02-01 23:18:00 +00:00
|
|
|
|
2017-02-01 23:51:25 +00:00
|
|
|
// Attempt to lookup the node by its node ID
|
2021-08-19 21:17:59 +00:00
|
|
|
iter, err := tx.Get(tableNodes, indexUUID+"_prefix", Query{
|
|
|
|
Value: resizeNodeLookupKey(nodeNameOrID),
|
|
|
|
EnterpriseMeta: *entMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: peerName,
|
2021-08-19 21:17:59 +00:00
|
|
|
})
|
2017-02-01 23:18:00 +00:00
|
|
|
if err != nil {
|
2017-02-01 23:51:25 +00:00
|
|
|
ws.Add(watchCh)
|
2022-06-23 15:13:25 +00:00
|
|
|
idx := catalogNodeLastExtinctionIndex(tx, entMeta, peerName)
|
|
|
|
return true, idx, nil, nil, nil
|
2017-02-01 23:18:00 +00:00
|
|
|
}
|
2017-02-01 23:51:25 +00:00
|
|
|
|
2017-02-01 23:18:00 +00:00
|
|
|
n = iter.Next()
|
|
|
|
if n == nil {
|
2017-02-01 23:51:25 +00:00
|
|
|
// No nodes matched, even with the Node ID: add a watch on the node name.
|
2017-02-01 23:18:00 +00:00
|
|
|
ws.Add(watchCh)
|
2022-06-23 15:13:25 +00:00
|
|
|
idx := catalogNodeLastExtinctionIndex(tx, entMeta, peerName)
|
|
|
|
return true, idx, nil, nil, nil
|
2017-02-01 23:18:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
idWatchCh := iter.WatchCh()
|
|
|
|
if iter.Next() != nil {
|
2017-02-01 23:51:25 +00:00
|
|
|
// More than one match present: Watch on the node name channel and return
|
|
|
|
// an empty result (node lookups can not be ambiguous).
|
2017-02-01 23:18:00 +00:00
|
|
|
ws.Add(watchCh)
|
2019-12-10 02:26:41 +00:00
|
|
|
return true, 0, nil, nil, nil
|
2017-02-01 23:18:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ws.Add(idWatchCh)
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
2017-02-01 22:20:25 +00:00
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
node := n.(*structs.Node)
|
2017-02-01 23:41:10 +00:00
|
|
|
nodeName := node.Node
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// Read all of the services
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
services, err := catalogServiceListByNode(tx, nodeName, entMeta, peerName, allowWildcard)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
return true, 0, nil, nil, fmt.Errorf("failed querying services for node %q: %s", nodeName, err)
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
2017-01-20 07:36:50 +00:00
|
|
|
ws.Add(services.WatchCh())
|
2017-01-13 19:47:16 +00:00
|
|
|
|
2022-06-23 15:13:25 +00:00
|
|
|
// Get the table index.
|
|
|
|
idx := catalogNodeMaxIndex(tx, nodeName, entMeta, peerName)
|
|
|
|
|
2019-12-10 02:26:41 +00:00
|
|
|
return false, idx, node, services, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// NodeServices is used to query service registrations by node name or UUID.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) NodeServices(ws memdb.WatchSet, nodeNameOrID string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, *structs.NodeServices, error) {
|
|
|
|
done, idx, node, services, err := s.nodeServices(ws, nodeNameOrID, entMeta, peerName, false)
|
2019-12-10 02:26:41 +00:00
|
|
|
if done || err != nil {
|
|
|
|
return idx, nil, err
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// Initialize the node services struct
|
|
|
|
ns := &structs.NodeServices{
|
|
|
|
Node: node,
|
|
|
|
Services: make(map[string]*structs.NodeService),
|
|
|
|
}
|
|
|
|
|
2019-12-10 02:26:41 +00:00
|
|
|
if services != nil {
|
|
|
|
// Add all of the services to the map.
|
|
|
|
for service := services.Next(); service != nil; service = services.Next() {
|
|
|
|
svc := service.(*structs.ServiceNode).ToNodeService()
|
|
|
|
ns.Services[svc.ID] = svc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return idx, ns, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// NodeServices is used to query service registrations by node name or UUID.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) NodeServiceList(ws memdb.WatchSet, nodeNameOrID string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, *structs.NodeServiceList, error) {
|
|
|
|
done, idx, node, services, err := s.nodeServices(ws, nodeNameOrID, entMeta, peerName, true)
|
2019-12-10 02:26:41 +00:00
|
|
|
if done || err != nil {
|
|
|
|
return idx, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if idx == 0 {
|
|
|
|
return 0, nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the node services struct
|
|
|
|
ns := &structs.NodeServiceList{
|
|
|
|
Node: node,
|
|
|
|
}
|
|
|
|
|
|
|
|
if services != nil {
|
|
|
|
// Add all of the services to the map.
|
|
|
|
for service := services.Next(); service != nil; service = services.Next() {
|
|
|
|
svc := service.(*structs.ServiceNode).ToNodeService()
|
|
|
|
ns.Services = append(ns.Services, svc)
|
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return idx, ns, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteService is used to delete a given service associated with a node.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) DeleteService(idx uint64, nodeName, serviceID string, entMeta *acl.EnterpriseMeta, peerName string) error {
|
2020-03-19 13:11:20 +00:00
|
|
|
tx := s.db.WriteTxn(idx)
|
2017-01-13 19:47:16 +00:00
|
|
|
defer tx.Abort()
|
|
|
|
|
|
|
|
// Call the service deletion
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := s.deleteServiceTxn(tx, idx, nodeName, serviceID, entMeta, peerName); err != nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-06-02 20:34:56 +00:00
|
|
|
return tx.Commit()
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2018-12-03 08:41:24 +00:00
|
|
|
// deleteServiceCASTxn is used to try doing a service delete operation with a given
|
|
|
|
// raft index. If the CAS index specified is not equal to the last observed index for
|
|
|
|
// the given service, then the call is a noop, otherwise a normal delete is invoked.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) deleteServiceCASTxn(tx WriteTxn, idx, cidx uint64, nodeName, serviceID string, entMeta *acl.EnterpriseMeta, peerName string) (bool, error) {
|
2018-12-03 08:41:24 +00:00
|
|
|
// Look up the service.
|
2022-05-27 11:38:52 +00:00
|
|
|
service, err := getNodeServiceTxn(tx, nil, nodeName, serviceID, entMeta, peerName)
|
2018-12-03 08:41:24 +00:00
|
|
|
if err != nil {
|
2019-01-09 19:59:23 +00:00
|
|
|
return false, fmt.Errorf("service lookup failed: %s", err)
|
2018-12-03 08:41:24 +00:00
|
|
|
}
|
|
|
|
if service == nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the existing index does not match the provided CAS
|
|
|
|
// index arg, then we shouldn't update anything and can safely
|
|
|
|
// return early here.
|
2019-01-09 19:59:23 +00:00
|
|
|
if service.ModifyIndex != cidx {
|
|
|
|
return false, nil
|
2018-12-03 08:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Call the actual deletion if the above passed.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := s.deleteServiceTxn(tx, idx, nodeName, serviceID, entMeta, peerName); err != nil {
|
2018-12-03 08:41:24 +00:00
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// deleteServiceTxn is the inner method called to remove a service
|
|
|
|
// registration within an existing transaction.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) deleteServiceTxn(tx WriteTxn, idx uint64, nodeName, serviceID string, entMeta *acl.EnterpriseMeta, peerName string) error {
|
2021-02-12 18:39:38 +00:00
|
|
|
// TODO: pass non-pointer type for ent meta
|
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-02-12 18:39:38 +00:00
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
service, err := tx.First(tableServices, indexID,
|
|
|
|
NodeServiceQuery{
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
Node: nodeName,
|
|
|
|
Service: serviceID,
|
|
|
|
PeerName: peerName,
|
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed service lookup: %s", err)
|
|
|
|
}
|
|
|
|
if service == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete any checks associated with the service. This will invalidate
|
|
|
|
// sessions as necessary.
|
2021-08-17 18:29:39 +00:00
|
|
|
nsq := NodeServiceQuery{
|
|
|
|
Node: nodeName,
|
|
|
|
Service: serviceID,
|
|
|
|
EnterpriseMeta: *entMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: peerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
}
|
2021-03-26 21:21:38 +00:00
|
|
|
checks, err := tx.Get(tableChecks, indexNodeService, nsq)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed service check lookup: %s", err)
|
|
|
|
}
|
2019-12-10 02:26:41 +00:00
|
|
|
var deleteChecks []*structs.HealthCheck
|
2017-01-13 19:47:16 +00:00
|
|
|
for check := checks.Next(); check != nil; check = checks.Next() {
|
2019-12-10 02:26:41 +00:00
|
|
|
deleteChecks = append(deleteChecks, check.(*structs.HealthCheck))
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Do the delete in a separate loop so we don't trash the iterator.
|
2019-12-10 02:26:41 +00:00
|
|
|
for _, check := range deleteChecks {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := s.deleteCheckTxn(tx, idx, nodeName, check.CheckID, &check.EnterpriseMeta, check.PeerName); err != nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := catalogUpdateCheckIndexes(tx, idx, entMeta, peerName); err != nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
return err
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Delete the service and update the index
|
2021-03-26 20:04:45 +00:00
|
|
|
if err := tx.Delete(tableServices, service); err != nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return fmt.Errorf("failed deleting service: %s", err)
|
|
|
|
}
|
|
|
|
|
2018-02-19 17:29:22 +00:00
|
|
|
svc := service.(*structs.ServiceNode)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := catalogUpdateServicesIndexes(tx, idx, entMeta, svc.PeerName); err != nil {
|
2022-06-23 15:13:25 +00:00
|
|
|
return fmt.Errorf("failed updating services indexes: %w", err)
|
2019-07-12 21:19:37 +00:00
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := catalogUpdateServiceKindIndexes(tx, idx, svc.ServiceKind, &svc.EnterpriseMeta, svc.PeerName); err != nil {
|
2022-06-23 15:13:25 +00:00
|
|
|
return fmt.Errorf("failed updating service-kind indexes: %w", err)
|
|
|
|
}
|
|
|
|
// Update the node indexes as the service information is included in node catalog queries.
|
|
|
|
if err := catalogUpdateNodesIndexes(tx, idx, entMeta, peerName); err != nil {
|
|
|
|
return fmt.Errorf("failed updating nodes indexes: %w", err)
|
|
|
|
}
|
|
|
|
if err := catalogUpdateNodeIndexes(tx, idx, nodeName, entMeta, peerName); err != nil {
|
|
|
|
return fmt.Errorf("failed updating node indexes: %w", err)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
name := svc.CompoundServiceName()
|
|
|
|
|
2020-09-27 18:38:32 +00:00
|
|
|
if err := cleanupMeshTopology(tx, idx, svc); err != nil {
|
2020-10-02 00:10:49 +00:00
|
|
|
return fmt.Errorf("failed to clean up mesh-topology associations for %q: %v", name.String(), err)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
2019-07-12 21:19:37 +00:00
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
Value: svc.ServiceName,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: svc.PeerName,
|
|
|
|
}
|
2021-03-26 21:21:38 +00:00
|
|
|
if remainingService, err := tx.First(tableServices, indexService, q); err == nil {
|
2018-02-19 21:44:49 +00:00
|
|
|
if remainingService != nil {
|
2018-02-19 17:29:22 +00:00
|
|
|
// We have at least one remaining service, update the index
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := catalogUpdateServiceIndexes(tx, idx, svc.ServiceName, entMeta, svc.PeerName); err != nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
return err
|
2018-02-19 17:29:22 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// There are no more service instances, cleanup the service.<serviceName> index
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
_, serviceIndex, err := catalogServiceMaxIndex(tx, svc.ServiceName, entMeta, svc.PeerName)
|
2018-02-19 17:29:22 +00:00
|
|
|
if err == nil && serviceIndex != nil {
|
|
|
|
// we found service.<serviceName> index, garbage collect it
|
2022-06-23 15:13:25 +00:00
|
|
|
if err := tx.Delete(tableIndex, serviceIndex); err != nil {
|
2018-02-19 17:29:22 +00:00
|
|
|
return fmt.Errorf("[FAILED] deleting serviceIndex %s: %s", svc.ServiceName, err)
|
|
|
|
}
|
|
|
|
}
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := catalogUpdateServiceExtinctionIndex(tx, idx, entMeta, svc.PeerName); err != nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
return err
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
}
|
2022-06-24 18:38:39 +00:00
|
|
|
psn := structs.PeeredServiceName{Peer: svc.PeerName, ServiceName: name}
|
2022-07-21 12:38:28 +00:00
|
|
|
if err := freeServiceVirtualIP(tx, idx, psn, nil); err != nil {
|
2021-12-02 23:42:47 +00:00
|
|
|
return fmt.Errorf("failed to clean up virtual IP for %q: %v", name.String(), err)
|
|
|
|
}
|
2021-12-02 00:44:13 +00:00
|
|
|
if err := cleanupKindServiceName(tx, idx, svc.CompoundServiceName(), svc.ServiceKind); err != nil {
|
|
|
|
return fmt.Errorf("failed to persist service name: %v", err)
|
|
|
|
}
|
2018-02-19 17:29:22 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return fmt.Errorf("Could not find any service %s: %s", svc.ServiceName, err)
|
|
|
|
}
|
2020-04-08 18:37:24 +00:00
|
|
|
|
2023-02-21 19:59:36 +00:00
|
|
|
// Cleanup ConnectEnabled for this service if none exist.
|
|
|
|
if svc.PeerName == "" && (svc.ServiceKind == structs.ServiceKindConnectProxy || svc.ServiceConnect.Native) {
|
|
|
|
service := svc.ServiceName
|
|
|
|
if svc.ServiceKind == structs.ServiceKindConnectProxy {
|
|
|
|
service = svc.ServiceProxy.DestinationServiceName
|
|
|
|
}
|
|
|
|
sn := structs.ServiceName{Name: service, EnterpriseMeta: svc.EnterpriseMeta}
|
|
|
|
connectEnabled, err := serviceHasConnectEnabledInstances(tx, sn.Name, &sn.EnterpriseMeta)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to search for connect instances for service %q: %w", sn.Name, err)
|
|
|
|
}
|
|
|
|
if !connectEnabled {
|
|
|
|
if err := cleanupKindServiceName(tx, idx, sn, structs.ServiceKindConnectEnabled); err != nil {
|
|
|
|
return fmt.Errorf("failed to cleanup connect-enabled service name: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-28 19:51:01 +00:00
|
|
|
if svc.PeerName == "" {
|
2022-08-08 17:44:18 +00:00
|
|
|
sn := structs.ServiceName{Name: svc.ServiceName, EnterpriseMeta: svc.EnterpriseMeta}
|
|
|
|
if err := cleanupGatewayWildcards(tx, idx, sn, false); err != nil {
|
2022-07-28 19:51:01 +00:00
|
|
|
return fmt.Errorf("failed to clean up gateway-service associations for %q: %v", name.String(), err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-12-02 23:42:47 +00:00
|
|
|
// freeServiceVirtualIP is used to free a virtual IP for a service after the last instance
|
|
|
|
// is removed.
|
2022-06-24 18:38:39 +00:00
|
|
|
func freeServiceVirtualIP(
|
|
|
|
tx WriteTxn,
|
2022-07-21 12:38:28 +00:00
|
|
|
idx uint64,
|
2022-06-24 18:38:39 +00:00
|
|
|
psn structs.PeeredServiceName,
|
|
|
|
excludeGateway *structs.ServiceName,
|
|
|
|
) error {
|
2021-12-02 23:42:47 +00:00
|
|
|
supported, err := virtualIPsSupported(tx, nil)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if !supported {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-01-12 20:08:49 +00:00
|
|
|
// Don't deregister the virtual IP if at least one terminating gateway still references this service.
|
|
|
|
termGatewaySupported, err := terminatingGatewayVirtualIPsSupported(tx, nil)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if termGatewaySupported {
|
2022-06-24 18:38:39 +00:00
|
|
|
svcGateways, err := tx.Get(tableGatewayServices, indexService, psn.ServiceName)
|
2022-01-12 20:08:49 +00:00
|
|
|
if err != nil {
|
2022-06-24 18:38:39 +00:00
|
|
|
return fmt.Errorf("failed gateway lookup for %q: %s", psn.ServiceName.Name, err)
|
2022-01-12 20:08:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for service := svcGateways.Next(); service != nil; service = svcGateways.Next() {
|
|
|
|
if svc, ok := service.(*structs.GatewayService); ok && svc != nil {
|
|
|
|
ignoreGateway := excludeGateway == nil || !svc.Gateway.Matches(*excludeGateway)
|
|
|
|
if ignoreGateway && svc.GatewayKind == structs.ServiceKindTerminatingGateway {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-24 18:38:39 +00:00
|
|
|
serviceVIP, err := tx.First(tableServiceVirtualIPs, indexID, psn)
|
2021-12-02 23:42:47 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed service virtual IP lookup: %s", err)
|
|
|
|
}
|
|
|
|
// Service has no virtual IP assigned, nothing to do.
|
|
|
|
if serviceVIP == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete the service virtual IP and add it to the freed IPs list.
|
|
|
|
if err := tx.Delete(tableServiceVirtualIPs, serviceVIP); err != nil {
|
|
|
|
return fmt.Errorf("failed updating freed virtual IP table: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
newEntry := FreeVirtualIP{IP: serviceVIP.(ServiceVirtualIP).IP}
|
|
|
|
if err := tx.Insert(tableFreeVirtualIPs, newEntry); err != nil {
|
|
|
|
return fmt.Errorf("failed updating freed virtual IP table: %v", err)
|
|
|
|
}
|
|
|
|
|
2022-07-21 12:38:28 +00:00
|
|
|
if err := updateVirtualIPMaxIndexes(tx, idx, psn.ServiceName.PartitionOrDefault(), psn.Peer); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-12-02 23:42:47 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// EnsureCheck is used to store a check registration in the db.
|
2017-04-21 00:46:29 +00:00
|
|
|
func (s *Store) EnsureCheck(idx uint64, hc *structs.HealthCheck) error {
|
2020-03-19 13:11:20 +00:00
|
|
|
tx := s.db.WriteTxn(idx)
|
2017-01-13 19:47:16 +00:00
|
|
|
defer tx.Abort()
|
|
|
|
|
|
|
|
// Call the check registration
|
2020-08-11 05:52:36 +00:00
|
|
|
if err := s.ensureCheckTxn(tx, idx, false, hc); err != nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-06-02 20:34:56 +00:00
|
|
|
return tx.Commit()
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2018-03-22 09:30:05 +00:00
|
|
|
// updateAllServiceIndexesOfNode updates the Raft index of all the services associated with this node
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func updateAllServiceIndexesOfNode(tx WriteTxn, idx uint64, nodeID string, entMeta *acl.EnterpriseMeta, peerName string) error {
|
|
|
|
if peerName == "" {
|
|
|
|
peerName = structs.LocalPeerKeyword
|
|
|
|
}
|
2021-08-17 18:29:39 +00:00
|
|
|
services, err := tx.Get(tableServices, indexNode, Query{
|
|
|
|
Value: nodeID,
|
2021-09-17 23:36:20 +00:00
|
|
|
EnterpriseMeta: *entMeta.WithWildcardNamespace(),
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: peerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2018-03-19 15:12:54 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed updating services for node %s: %s", nodeID, err)
|
|
|
|
}
|
|
|
|
for service := services.Next(); service != nil; service = services.Next() {
|
2019-12-10 02:26:41 +00:00
|
|
|
svc := service.(*structs.ServiceNode)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := catalogUpdateServiceIndexes(tx, idx, svc.ServiceName, &svc.EnterpriseMeta, svc.PeerName); err != nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
return err
|
2019-06-20 19:04:39 +00:00
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := catalogUpdateServiceKindIndexes(tx, idx, svc.ServiceKind, &svc.EnterpriseMeta, svc.PeerName); err != nil {
|
2019-12-19 16:15:37 +00:00
|
|
|
return err
|
|
|
|
}
|
2018-03-19 13:14:03 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-10-29 18:41:42 +00:00
|
|
|
// ensureCheckCASTxn updates a check only if the existing index matches the given index.
|
|
|
|
// Returns a bool indicating if a write happened and any error.
|
2020-09-03 23:38:03 +00:00
|
|
|
func (s *Store) ensureCheckCASTxn(tx WriteTxn, idx uint64, hc *structs.HealthCheck) (bool, error) {
|
2018-10-29 18:41:42 +00:00
|
|
|
// Retrieve the existing entry.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
_, existing, err := getNodeCheckTxn(tx, hc.Node, hc.CheckID, &hc.EnterpriseMeta, hc.PeerName)
|
2018-10-29 18:41:42 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, fmt.Errorf("failed health check lookup: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if the we should do the set. A ModifyIndex of 0 means that
|
|
|
|
// we are doing a set-if-not-exists.
|
|
|
|
if hc.ModifyIndex == 0 && existing != nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
if hc.ModifyIndex != 0 && existing == nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
2019-01-09 19:59:23 +00:00
|
|
|
if existing != nil && hc.ModifyIndex != 0 && hc.ModifyIndex != existing.ModifyIndex {
|
2018-10-29 18:41:42 +00:00
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Perform the update.
|
2020-08-11 05:52:36 +00:00
|
|
|
if err := s.ensureCheckTxn(tx, idx, false, hc); err != nil {
|
2018-10-29 18:41:42 +00:00
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2020-03-19 13:11:20 +00:00
|
|
|
// ensureCheckTxn is used as the inner method to handle inserting
|
2017-01-13 19:47:16 +00:00
|
|
|
// a health check into the state store. It ensures safety against inserting
|
|
|
|
// checks with no matching node or service.
|
2020-09-03 23:38:03 +00:00
|
|
|
func (s *Store) ensureCheckTxn(tx WriteTxn, idx uint64, preserveIndexes bool, hc *structs.HealthCheck) error {
|
2017-01-13 19:47:16 +00:00
|
|
|
// Check if we have an existing health check
|
2021-08-17 18:29:39 +00:00
|
|
|
existing, err := tx.First(tableChecks, indexID, NodeCheckQuery{
|
|
|
|
EnterpriseMeta: hc.EnterpriseMeta,
|
|
|
|
Node: hc.Node,
|
|
|
|
CheckID: string(hc.CheckID),
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: hc.PeerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed health check lookup: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the indexes
|
|
|
|
if existing != nil {
|
2018-10-11 11:42:39 +00:00
|
|
|
existingCheck := existing.(*structs.HealthCheck)
|
|
|
|
hc.CreateIndex = existingCheck.CreateIndex
|
|
|
|
hc.ModifyIndex = existingCheck.ModifyIndex
|
2020-08-11 05:52:36 +00:00
|
|
|
} else if !preserveIndexes {
|
2017-01-13 19:47:16 +00:00
|
|
|
hc.CreateIndex = idx
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use the default check status if none was provided
|
|
|
|
if hc.Status == "" {
|
2017-04-19 23:00:11 +00:00
|
|
|
hc.Status = api.HealthCritical
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get the node
|
2021-08-17 18:29:39 +00:00
|
|
|
node, err := tx.First(tableNodes, indexID, Query{
|
|
|
|
Value: hc.Node,
|
|
|
|
EnterpriseMeta: hc.EnterpriseMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: hc.PeerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed node lookup: %s", err)
|
|
|
|
}
|
|
|
|
if node == nil {
|
|
|
|
return ErrMissingNode
|
|
|
|
}
|
|
|
|
|
2018-10-11 11:42:39 +00:00
|
|
|
modified := true
|
2017-01-13 19:47:16 +00:00
|
|
|
// If the check is associated with a service, check that we have
|
|
|
|
// a registration for the service.
|
|
|
|
if hc.ServiceID != "" {
|
2021-08-17 18:29:39 +00:00
|
|
|
service, err := tx.First(tableServices, indexID, NodeServiceQuery{
|
|
|
|
EnterpriseMeta: hc.EnterpriseMeta,
|
|
|
|
Node: hc.Node,
|
|
|
|
Service: hc.ServiceID,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: hc.PeerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed service lookup: %s", err)
|
|
|
|
}
|
|
|
|
if service == nil {
|
|
|
|
return ErrMissingService
|
|
|
|
}
|
|
|
|
|
2017-04-27 23:03:05 +00:00
|
|
|
// Copy in the service name and tags
|
|
|
|
svc := service.(*structs.ServiceNode)
|
|
|
|
hc.ServiceName = svc.ServiceName
|
|
|
|
hc.ServiceTags = svc.ServiceTags
|
2018-10-11 11:42:39 +00:00
|
|
|
if existing != nil && existing.(*structs.HealthCheck).IsSame(hc) {
|
|
|
|
modified = false
|
|
|
|
} else {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err = catalogUpdateServiceIndexes(tx, idx, svc.ServiceName, &svc.EnterpriseMeta, svc.PeerName); err != nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
return err
|
2019-06-20 19:04:39 +00:00
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := catalogUpdateServiceKindIndexes(tx, idx, svc.ServiceKind, &svc.EnterpriseMeta, svc.PeerName); err != nil {
|
2019-12-19 16:15:37 +00:00
|
|
|
return err
|
|
|
|
}
|
2018-02-19 17:29:22 +00:00
|
|
|
}
|
|
|
|
} else {
|
2018-10-11 11:42:39 +00:00
|
|
|
if existing != nil && existing.(*structs.HealthCheck).IsSame(hc) {
|
|
|
|
modified = false
|
|
|
|
} else {
|
|
|
|
// Since the check has been modified, it impacts all services of node
|
|
|
|
// Update the status for all the services associated with this node
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
err = updateAllServiceIndexesOfNode(tx, idx, hc.Node, &hc.EnterpriseMeta, hc.PeerName)
|
2018-10-11 11:42:39 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-02-19 17:29:22 +00:00
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Delete any sessions for this check if the health is critical.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if hc.Status == api.HealthCritical && hc.PeerName == "" {
|
2019-12-10 02:26:41 +00:00
|
|
|
sessions, err := checkSessionsTxn(tx, hc)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
return err
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Delete the session in a separate loop so we don't trash the
|
|
|
|
// iterator.
|
2019-12-10 02:26:41 +00:00
|
|
|
for _, sess := range sessions {
|
|
|
|
if err := s.deleteSessionTxn(tx, idx, sess.Session, &sess.EnterpriseMeta); err != nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return fmt.Errorf("failed deleting session: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-19 13:11:20 +00:00
|
|
|
if !modified {
|
|
|
|
return nil
|
2018-10-11 11:42:39 +00:00
|
|
|
}
|
2020-08-11 05:52:36 +00:00
|
|
|
if !preserveIndexes {
|
|
|
|
hc.ModifyIndex = idx
|
|
|
|
}
|
|
|
|
|
2020-07-10 00:56:43 +00:00
|
|
|
return catalogInsertCheck(tx, hc, idx)
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NodeCheck is used to retrieve a specific check associated with the given
|
|
|
|
// node.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) NodeCheck(nodeName string, checkID types.CheckID, entMeta *acl.EnterpriseMeta, peerName string) (uint64, *structs.HealthCheck, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return getNodeCheckTxn(tx, nodeName, checkID, entMeta, peerName)
|
2018-10-29 18:41:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// nodeCheckTxn is used as the inner method to handle reading a health check
|
|
|
|
// from the state store.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func getNodeCheckTxn(tx ReadTxn, nodeName string, checkID types.CheckID, entMeta *acl.EnterpriseMeta, peerName string) (uint64, *structs.HealthCheck, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
// Get the table index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogChecksMaxIndex(tx, entMeta, peerName)
|
2017-01-13 19:47:16 +00:00
|
|
|
|
2021-02-12 23:06:56 +00:00
|
|
|
// TODO: accept non-pointer value
|
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-02-12 23:06:56 +00:00
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// Return the check.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
check, err := tx.First(tableChecks, indexID,
|
|
|
|
NodeCheckQuery{
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
Node: nodeName,
|
|
|
|
CheckID: string(checkID),
|
|
|
|
PeerName: peerName,
|
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed check lookup: %s", err)
|
|
|
|
}
|
2017-01-24 07:37:21 +00:00
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
if check != nil {
|
|
|
|
return idx, check.(*structs.HealthCheck), nil
|
|
|
|
}
|
2017-04-21 01:59:42 +00:00
|
|
|
return idx, nil, nil
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NodeChecks is used to retrieve checks associated with the
|
|
|
|
// given node from the state store.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) NodeChecks(ws memdb.WatchSet, nodeName string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.HealthChecks, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
2021-02-12 22:31:02 +00:00
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-02-12 22:31:02 +00:00
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// Get the table index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogChecksMaxIndex(tx, entMeta, peerName)
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// Return the checks.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
iter, err := catalogListChecksByNode(tx, Query{
|
|
|
|
Value: nodeName,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed check lookup: %s", err)
|
|
|
|
}
|
2017-01-24 07:37:21 +00:00
|
|
|
ws.Add(iter.WatchCh())
|
|
|
|
|
|
|
|
var results structs.HealthChecks
|
|
|
|
for check := iter.Next(); check != nil; check = iter.Next() {
|
|
|
|
results = append(results, check.(*structs.HealthCheck))
|
|
|
|
}
|
|
|
|
return idx, results, nil
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ServiceChecks is used to get all checks associated with a
|
|
|
|
// given service ID. The query is performed against a service
|
|
|
|
// _name_ instead of a service ID.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) ServiceChecks(ws memdb.WatchSet, serviceName string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.HealthChecks, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
|
|
|
// Get the table index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogChecksMaxIndex(tx, entMeta, peerName)
|
2017-01-13 19:47:16 +00:00
|
|
|
|
2021-03-29 20:37:37 +00:00
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-03-29 20:37:37 +00:00
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
Value: serviceName,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
}
|
2021-03-29 20:37:37 +00:00
|
|
|
iter, err := tx.Get(tableChecks, indexService, q)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed check lookup: %s", err)
|
|
|
|
}
|
2017-01-24 07:37:21 +00:00
|
|
|
ws.Add(iter.WatchCh())
|
|
|
|
|
|
|
|
var results structs.HealthChecks
|
|
|
|
for check := iter.Next(); check != nil; check = iter.Next() {
|
|
|
|
results = append(results, check.(*structs.HealthCheck))
|
|
|
|
}
|
|
|
|
return idx, results, nil
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2017-01-14 01:08:43 +00:00
|
|
|
// ServiceChecksByNodeMeta is used to get all checks associated with a
|
2017-01-14 01:45:34 +00:00
|
|
|
// given service ID, filtered by the given node metadata values. The query
|
|
|
|
// is performed against a service _name_ instead of a service ID.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) ServiceChecksByNodeMeta(ws memdb.WatchSet, serviceName string, filters map[string]string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.HealthChecks, error) {
|
2017-01-14 01:08:43 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
|
|
|
// Get the table index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := maxIndexForService(tx, serviceName, true, true, entMeta, peerName)
|
2021-03-29 20:37:37 +00:00
|
|
|
|
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-03-29 20:37:37 +00:00
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
Value: serviceName,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
}
|
2021-03-29 20:37:37 +00:00
|
|
|
iter, err := tx.Get(tableChecks, indexService, q)
|
2017-01-14 01:08:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed check lookup: %s", err)
|
|
|
|
}
|
2017-01-24 07:37:21 +00:00
|
|
|
ws.Add(iter.WatchCh())
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return parseChecksByNodeMeta(tx, ws, idx, iter, filters, entMeta, peerName)
|
2017-01-14 01:08:43 +00:00
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// ChecksInState is used to query the state store for all checks
|
|
|
|
// which are in the provided state.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) ChecksInState(ws memdb.WatchSet, state string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.HealthChecks, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx, iter, err := checksInStateTxn(tx, ws, state, entMeta, peerName)
|
2017-04-27 23:03:05 +00:00
|
|
|
if err != nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
return 0, nil, err
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 07:37:21 +00:00
|
|
|
var results structs.HealthChecks
|
|
|
|
for check := iter.Next(); check != nil; check = iter.Next() {
|
|
|
|
results = append(results, check.(*structs.HealthCheck))
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
2017-01-24 07:37:21 +00:00
|
|
|
return idx, results, nil
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2017-01-14 01:45:34 +00:00
|
|
|
// ChecksInStateByNodeMeta is used to query the state store for all checks
|
|
|
|
// which are in the provided state, filtered by the given node metadata values.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) ChecksInStateByNodeMeta(ws memdb.WatchSet, state string, filters map[string]string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.HealthChecks, error) {
|
2017-01-14 01:08:43 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx, iter, err := checksInStateTxn(tx, ws, state, entMeta, peerName)
|
2019-12-10 02:26:41 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, err
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return parseChecksByNodeMeta(tx, ws, idx, iter, filters, entMeta, peerName)
|
2019-12-10 02:26:41 +00:00
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func checksInStateTxn(tx ReadTxn, ws memdb.WatchSet, state string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, memdb.ResultIterator, error) {
|
2017-01-14 01:08:43 +00:00
|
|
|
// Get the table index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogChecksMaxIndex(tx, entMeta, peerName)
|
2017-01-14 01:08:43 +00:00
|
|
|
|
2021-03-29 20:29:04 +00:00
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-03-29 20:29:04 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 07:37:21 +00:00
|
|
|
// Query all checks if HealthAny is passed, otherwise use the index.
|
|
|
|
var iter memdb.ResultIterator
|
2017-01-14 01:08:43 +00:00
|
|
|
var err error
|
2017-04-19 23:00:11 +00:00
|
|
|
if state == api.HealthAny {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
}
|
|
|
|
iter, err = tx.Get(tableChecks, indexID+"_prefix", q)
|
2017-01-14 01:08:43 +00:00
|
|
|
} else {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
Value: state,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
}
|
2021-03-29 20:29:04 +00:00
|
|
|
iter, err = tx.Get(tableChecks, indexStatus, q)
|
2019-12-10 02:26:41 +00:00
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed check lookup: %s", err)
|
2017-01-14 01:08:43 +00:00
|
|
|
}
|
2017-01-24 07:37:21 +00:00
|
|
|
ws.Add(iter.WatchCh())
|
2017-01-14 01:08:43 +00:00
|
|
|
|
2019-12-10 02:26:41 +00:00
|
|
|
return idx, iter, err
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2017-01-14 01:08:43 +00:00
|
|
|
// parseChecksByNodeMeta is a helper function used to deduplicate some
|
|
|
|
// repetitive code for returning health checks filtered by node metadata fields.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func parseChecksByNodeMeta(
|
|
|
|
tx ReadTxn,
|
|
|
|
ws memdb.WatchSet,
|
|
|
|
idx uint64,
|
|
|
|
iter memdb.ResultIterator,
|
|
|
|
filters map[string]string,
|
|
|
|
entMeta *acl.EnterpriseMeta,
|
|
|
|
peerName string,
|
|
|
|
) (uint64, structs.HealthChecks, error) {
|
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
2017-01-24 07:37:21 +00:00
|
|
|
|
|
|
|
// We don't want to track an unlimited number of nodes, so we pull a
|
|
|
|
// top-level watch to use as a fallback.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
}
|
|
|
|
allNodes, err := tx.Get(tableNodes, indexID+"_prefix", q)
|
2017-01-24 07:37:21 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed nodes lookup: %s", err)
|
|
|
|
}
|
|
|
|
allNodesCh := allNodes.WatchCh()
|
|
|
|
|
|
|
|
// Only take results for nodes that satisfy the node metadata filters.
|
2017-01-14 01:08:43 +00:00
|
|
|
var results structs.HealthChecks
|
|
|
|
for check := iter.Next(); check != nil; check = iter.Next() {
|
|
|
|
healthCheck := check.(*structs.HealthCheck)
|
2021-08-17 18:29:39 +00:00
|
|
|
watchCh, node, err := tx.FirstWatch(tableNodes, indexID, Query{
|
|
|
|
Value: healthCheck.Node,
|
|
|
|
EnterpriseMeta: healthCheck.EnterpriseMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: healthCheck.PeerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-14 01:08:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed node lookup: %s", err)
|
|
|
|
}
|
|
|
|
if node == nil {
|
|
|
|
return 0, nil, ErrMissingNode
|
|
|
|
}
|
2017-01-24 07:37:21 +00:00
|
|
|
|
|
|
|
// Add even the filtered nodes so we wake up if the node metadata
|
|
|
|
// changes.
|
|
|
|
ws.AddWithLimit(watchLimit, watchCh, allNodesCh)
|
2017-01-14 01:08:43 +00:00
|
|
|
if structs.SatisfiesMetaFilters(node.(*structs.Node).Meta, filters) {
|
|
|
|
results = append(results, healthCheck)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return idx, results, nil
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// DeleteCheck is used to delete a health check registration.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) DeleteCheck(idx uint64, node string, checkID types.CheckID, entMeta *acl.EnterpriseMeta, peerName string) error {
|
2020-03-19 13:11:20 +00:00
|
|
|
tx := s.db.WriteTxn(idx)
|
2017-01-13 19:47:16 +00:00
|
|
|
defer tx.Abort()
|
|
|
|
|
|
|
|
// Call the check deletion
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := s.deleteCheckTxn(tx, idx, node, checkID, entMeta, peerName); err != nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-06-02 20:34:56 +00:00
|
|
|
return tx.Commit()
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2018-10-29 18:41:42 +00:00
|
|
|
// deleteCheckCASTxn is used to try doing a check delete operation with a given
|
2018-12-03 07:11:48 +00:00
|
|
|
// raft index. If the CAS index specified is not equal to the last observed index for
|
2018-10-29 18:41:42 +00:00
|
|
|
// the given check, then the call is a noop, otherwise a normal check delete is invoked.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) deleteCheckCASTxn(
|
|
|
|
tx WriteTxn,
|
|
|
|
idx, cidx uint64,
|
|
|
|
node string,
|
|
|
|
checkID types.CheckID,
|
|
|
|
entMeta *acl.EnterpriseMeta,
|
|
|
|
peerName string,
|
|
|
|
) (bool, error) {
|
2018-10-29 18:41:42 +00:00
|
|
|
// Try to retrieve the existing health check.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
_, hc, err := getNodeCheckTxn(tx, node, checkID, entMeta, peerName)
|
2018-10-29 18:41:42 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, fmt.Errorf("check lookup failed: %s", err)
|
|
|
|
}
|
|
|
|
if hc == nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the existing index does not match the provided CAS
|
|
|
|
// index arg, then we shouldn't update anything and can safely
|
|
|
|
// return early here.
|
2019-01-09 19:59:23 +00:00
|
|
|
if hc.ModifyIndex != cidx {
|
|
|
|
return false, nil
|
2018-10-29 18:41:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Call the actual deletion if the above passed.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := s.deleteCheckTxn(tx, idx, node, checkID, entMeta, peerName); err != nil {
|
2018-10-29 18:41:42 +00:00
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2021-02-11 00:40:32 +00:00
|
|
|
// NodeServiceQuery is a type used to query the checks table.
|
|
|
|
type NodeServiceQuery struct {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
Node string
|
|
|
|
Service string
|
|
|
|
PeerName string
|
2022-04-05 21:10:06 +00:00
|
|
|
acl.EnterpriseMeta
|
2021-02-11 00:40:32 +00:00
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (q NodeServiceQuery) PeerOrEmpty() string {
|
|
|
|
return q.PeerName
|
|
|
|
}
|
|
|
|
|
2021-03-29 17:55:13 +00:00
|
|
|
// NamespaceOrDefault exists because structs.EnterpriseMeta uses a pointer
|
|
|
|
// receiver for this method. Remove once that is fixed.
|
|
|
|
func (q NodeServiceQuery) NamespaceOrDefault() string {
|
|
|
|
return q.EnterpriseMeta.NamespaceOrDefault()
|
|
|
|
}
|
|
|
|
|
2021-07-22 18:58:08 +00:00
|
|
|
// PartitionOrDefault exists because structs.EnterpriseMeta uses a pointer
|
|
|
|
// receiver for this method. Remove once that is fixed.
|
|
|
|
func (q NodeServiceQuery) PartitionOrDefault() string {
|
|
|
|
return q.EnterpriseMeta.PartitionOrDefault()
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// deleteCheckTxn is the inner method used to call a health
|
|
|
|
// check deletion within an existing transaction.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) deleteCheckTxn(tx WriteTxn, idx uint64, node string, checkID types.CheckID, entMeta *acl.EnterpriseMeta, peerName string) error {
|
2021-02-12 23:06:56 +00:00
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-02-12 23:06:56 +00:00
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// Try to retrieve the existing health check.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
hc, err := tx.First(tableChecks, indexID,
|
|
|
|
NodeCheckQuery{
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
Node: node,
|
|
|
|
CheckID: string(checkID),
|
|
|
|
PeerName: peerName,
|
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("check lookup failed: %s", err)
|
|
|
|
}
|
|
|
|
if hc == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2018-02-19 17:29:22 +00:00
|
|
|
existing := hc.(*structs.HealthCheck)
|
2018-03-19 13:14:03 +00:00
|
|
|
if existing != nil {
|
2018-03-19 15:12:54 +00:00
|
|
|
// When no service is linked to this service, update all services of node
|
|
|
|
if existing.ServiceID != "" {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := catalogUpdateServiceIndexes(tx, idx, existing.ServiceName, &existing.EnterpriseMeta, existing.PeerName); err != nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
return err
|
2018-03-19 15:12:54 +00:00
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
svcRaw, err := tx.First(tableServices, indexID,
|
|
|
|
NodeServiceQuery{
|
|
|
|
EnterpriseMeta: existing.EnterpriseMeta,
|
|
|
|
Node: existing.Node,
|
|
|
|
Service: existing.ServiceID,
|
|
|
|
PeerName: existing.PeerName,
|
|
|
|
})
|
2019-07-12 21:19:37 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed retrieving service from state store: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
svc := svcRaw.(*structs.ServiceNode)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := catalogUpdateServiceKindIndexes(tx, idx, svc.ServiceKind, &svc.EnterpriseMeta, svc.PeerName); err != nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
return err
|
2019-07-12 21:19:37 +00:00
|
|
|
}
|
2018-03-19 15:12:54 +00:00
|
|
|
} else {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := updateAllServiceIndexesOfNode(tx, idx, existing.Node, &existing.EnterpriseMeta, existing.PeerName); err != nil {
|
2018-03-19 15:12:54 +00:00
|
|
|
return fmt.Errorf("Failed to update services linked to deleted healthcheck: %s", err)
|
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := catalogUpdateServicesIndexes(tx, idx, entMeta, existing.PeerName); err != nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
return err
|
2018-03-19 15:12:54 +00:00
|
|
|
}
|
2018-02-19 17:29:22 +00:00
|
|
|
}
|
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// Delete the check from the DB and update the index.
|
2021-03-26 23:33:10 +00:00
|
|
|
if err := tx.Delete(tableChecks, hc); err != nil {
|
2017-01-13 19:47:16 +00:00
|
|
|
return fmt.Errorf("failed removing check: %s", err)
|
|
|
|
}
|
2019-12-10 02:26:41 +00:00
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if err := catalogUpdateCheckIndexes(tx, idx, entMeta, peerName); err != nil {
|
2019-12-10 02:26:41 +00:00
|
|
|
return err
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if peerName == "" {
|
|
|
|
// Delete any sessions for this check.
|
|
|
|
sessions, err := checkSessionsTxn(tx, existing)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
// Do the delete in a separate loop so we don't trash the iterator.
|
|
|
|
for _, sess := range sessions {
|
|
|
|
if err := s.deleteSessionTxn(tx, idx, sess.Session, &sess.EnterpriseMeta); err != nil {
|
|
|
|
return fmt.Errorf("failed deleting session: %s", err)
|
|
|
|
}
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-09-29 01:41:24 +00:00
|
|
|
// CombinedCheckServiceNodes is used to query all nodes and checks for both typical and Connect endpoints of a service
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) CombinedCheckServiceNodes(ws memdb.WatchSet, service structs.ServiceName, peerName string) (uint64, structs.CheckServiceNodes, error) {
|
2020-09-29 01:41:24 +00:00
|
|
|
var (
|
|
|
|
resp structs.CheckServiceNodes
|
|
|
|
maxIdx uint64
|
|
|
|
)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx, csn, err := s.CheckServiceNodes(ws, service.Name, &service.EnterpriseMeta, peerName)
|
2020-09-29 01:41:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed to get downstream nodes for %q: %v", service, err)
|
|
|
|
}
|
|
|
|
if idx > maxIdx {
|
|
|
|
maxIdx = idx
|
|
|
|
}
|
|
|
|
resp = append(resp, csn...)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx, csn, err = s.CheckConnectServiceNodes(ws, service.Name, &service.EnterpriseMeta, peerName)
|
2020-09-29 01:41:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed to get downstream connect nodes for %q: %v", service, err)
|
|
|
|
}
|
|
|
|
if idx > maxIdx {
|
|
|
|
maxIdx = idx
|
|
|
|
}
|
|
|
|
resp = append(resp, csn...)
|
|
|
|
|
|
|
|
return maxIdx, resp, nil
|
|
|
|
}
|
|
|
|
|
2017-01-16 18:28:46 +00:00
|
|
|
// CheckServiceNodes is used to query all nodes and checks for a given service.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) CheckServiceNodes(ws memdb.WatchSet, serviceName string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error) {
|
|
|
|
return s.checkServiceNodes(ws, serviceName, false, entMeta, peerName)
|
2018-03-09 17:32:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// CheckConnectServiceNodes is used to query all nodes and checks for Connect
|
|
|
|
// compatible endpoints for a given service.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) CheckConnectServiceNodes(ws memdb.WatchSet, serviceName string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error) {
|
|
|
|
return s.checkServiceNodes(ws, serviceName, true, entMeta, peerName)
|
2018-03-09 17:32:22 +00:00
|
|
|
}
|
|
|
|
|
2020-04-16 21:00:48 +00:00
|
|
|
// CheckIngressServiceNodes is used to query all nodes and checks for ingress
|
|
|
|
// endpoints for a given service.
|
2022-04-05 21:10:06 +00:00
|
|
|
func (s *Store) CheckIngressServiceNodes(ws memdb.WatchSet, serviceName string, entMeta *acl.EnterpriseMeta) (uint64, structs.CheckServiceNodes, error) {
|
2020-04-16 21:00:48 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
2020-04-29 22:52:27 +00:00
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
maxIdx, nodes, err := serviceGatewayNodes(tx, ws, serviceName, structs.ServiceKindIngressGateway, entMeta, structs.DefaultPeerKeyword)
|
2020-04-16 21:00:48 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed gateway nodes lookup: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO(ingress) : Deal with incorporating index from mapping table
|
2020-04-29 22:52:27 +00:00
|
|
|
// Watch for index changes to the gateway nodes
|
2020-07-10 00:56:43 +00:00
|
|
|
idx, chans := maxIndexAndWatchChsForServiceNodes(tx, nodes, false)
|
2020-04-29 22:52:27 +00:00
|
|
|
for _, ch := range chans {
|
2020-04-16 21:00:48 +00:00
|
|
|
ws.Add(ch)
|
|
|
|
}
|
2020-05-08 15:44:34 +00:00
|
|
|
maxIdx = lib.MaxUint64(maxIdx, idx)
|
2020-04-16 21:00:48 +00:00
|
|
|
|
|
|
|
// TODO(ingress): Test namespace functionality here
|
|
|
|
// De-dup services to lookup
|
2020-06-12 14:57:41 +00:00
|
|
|
names := make(map[structs.ServiceName]struct{})
|
2020-04-16 21:00:48 +00:00
|
|
|
for _, n := range nodes {
|
2020-06-12 14:57:41 +00:00
|
|
|
names[n.CompoundServiceName()] = struct{}{}
|
2020-04-16 21:00:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var results structs.CheckServiceNodes
|
2020-06-12 15:34:02 +00:00
|
|
|
for sn := range names {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx, n, err := checkServiceNodesTxn(tx, ws, sn.Name, false, &sn.EnterpriseMeta, structs.DefaultPeerKeyword)
|
2020-04-16 21:00:48 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, err
|
|
|
|
}
|
2020-04-23 23:16:04 +00:00
|
|
|
maxIdx = lib.MaxUint64(maxIdx, idx)
|
2020-04-16 21:00:48 +00:00
|
|
|
results = append(results, n...)
|
|
|
|
}
|
|
|
|
return maxIdx, results, nil
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) checkServiceNodes(ws memdb.WatchSet, serviceName string, connect bool, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return checkServiceNodesTxn(tx, ws, serviceName, connect, entMeta, peerName)
|
2020-04-16 21:00:48 +00:00
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func checkServiceNodesTxn(tx ReadTxn, ws memdb.WatchSet, serviceName string, connect bool, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error) {
|
2021-03-26 21:21:38 +00:00
|
|
|
index := indexService
|
2019-12-10 02:26:41 +00:00
|
|
|
if connect {
|
2021-03-26 21:21:38 +00:00
|
|
|
index = indexConnect
|
2018-03-09 17:32:22 +00:00
|
|
|
}
|
|
|
|
|
2021-03-26 21:21:38 +00:00
|
|
|
// TODO: accept non-pointer
|
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-03-26 21:21:38 +00:00
|
|
|
}
|
|
|
|
|
2021-08-17 18:29:39 +00:00
|
|
|
q := Query{
|
|
|
|
Value: serviceName,
|
|
|
|
EnterpriseMeta: *entMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: peerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
}
|
2021-03-26 21:21:38 +00:00
|
|
|
iter, err := tx.Get(tableServices, index, q)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed service lookup: %s", err)
|
|
|
|
}
|
2019-03-15 20:18:48 +00:00
|
|
|
// Note we decide if we want to watch this iterator or not down below. We need
|
|
|
|
// to see if it returned anything first.
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// Return the results.
|
|
|
|
var results structs.ServiceNodes
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
|
2019-03-21 16:01:56 +00:00
|
|
|
// For connect queries we need a list of any proxy service names in the result
|
|
|
|
// set. Rather than have different code path for connect and non-connect, we
|
|
|
|
// use the same one in both cases. For non-empty non-connect results,
|
|
|
|
// serviceNames will always have exactly one element which is the same as
|
|
|
|
// serviceName. For Connect there might be multiple different service names -
|
|
|
|
// one for each service name a proxy is registered under, and the target
|
|
|
|
// service name IFF there is at least one Connect-native instance of that
|
|
|
|
// service. Either way there is usually only one distinct name if proxies are
|
|
|
|
// named consistently but could be multiple.
|
2020-06-12 14:57:41 +00:00
|
|
|
serviceNames := make(map[structs.ServiceName]struct{}, 2)
|
2017-01-24 07:37:21 +00:00
|
|
|
for service := iter.Next(); service != nil; service = iter.Next() {
|
2019-03-21 16:01:56 +00:00
|
|
|
sn := service.(*structs.ServiceNode)
|
|
|
|
results = append(results, sn)
|
2020-05-08 15:44:34 +00:00
|
|
|
|
2020-06-12 14:57:41 +00:00
|
|
|
name := structs.NewServiceName(sn.ServiceName, &sn.EnterpriseMeta)
|
|
|
|
serviceNames[name] = struct{}{}
|
2019-03-21 16:01:56 +00:00
|
|
|
}
|
|
|
|
|
2020-04-16 21:00:48 +00:00
|
|
|
// If we are querying for Connect nodes, the associated proxy might be a terminating-gateway.
|
2020-04-08 18:37:24 +00:00
|
|
|
// Gateways are tracked in a separate table, and we append them to the result set.
|
|
|
|
// We append rather than replace since it allows users to migrate a service
|
|
|
|
// to the mesh with a mix of sidecars and gateways until all its instances have a sidecar.
|
2020-04-27 22:25:37 +00:00
|
|
|
var idx uint64
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if connect && peerName == "" {
|
2020-04-08 18:37:24 +00:00
|
|
|
// Look up gateway nodes associated with the service
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
// TODO(peering): we'll have to do something here
|
|
|
|
gwIdx, nodes, err := serviceGatewayNodes(tx, ws, serviceName, structs.ServiceKindTerminatingGateway, entMeta, structs.DefaultPeerKeyword)
|
2020-04-08 18:37:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed gateway nodes lookup: %v", err)
|
|
|
|
}
|
2020-04-23 23:16:04 +00:00
|
|
|
idx = lib.MaxUint64(idx, gwIdx)
|
2020-04-08 18:37:24 +00:00
|
|
|
for i := 0; i < len(nodes); i++ {
|
|
|
|
results = append(results, nodes[i])
|
2020-05-08 15:44:34 +00:00
|
|
|
|
2020-06-12 14:57:41 +00:00
|
|
|
name := structs.NewServiceName(nodes[i].ServiceName, &nodes[i].EnterpriseMeta)
|
|
|
|
serviceNames[name] = struct{}{}
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-21 16:01:56 +00:00
|
|
|
// watchOptimized tracks if we meet the necessary condition to optimize
|
|
|
|
// WatchSet size. That is that every service name represented in the result
|
|
|
|
// set must have a service-specific index we can watch instead of many radix
|
|
|
|
// nodes for all the actual nodes touched. This saves us watching potentially
|
|
|
|
// thousands of watch chans for large services which may need many goroutines.
|
|
|
|
// It also avoids the performance cliff that is hit when watchLimit is hit
|
|
|
|
// (~682 service instances). See
|
|
|
|
// https://github.com/hashicorp/consul/issues/4984
|
|
|
|
watchOptimized := false
|
|
|
|
if len(serviceNames) > 0 {
|
|
|
|
// Assume optimization will work since it really should at this point. For
|
|
|
|
// safety we'll sanity check this below for each service name.
|
|
|
|
watchOptimized = true
|
|
|
|
|
|
|
|
// Fetch indexes for all names services in result set.
|
2020-06-12 14:57:41 +00:00
|
|
|
for n := range serviceNames {
|
2019-03-21 16:01:56 +00:00
|
|
|
// We know service values should exist since the serviceNames map is only
|
|
|
|
// populated if there is at least one result above. so serviceExists arg
|
|
|
|
// below is always true.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
svcIdx, svcCh := maxIndexAndWatchChForService(tx, n.Name, true, true, &n.EnterpriseMeta, peerName)
|
2019-03-21 16:01:56 +00:00
|
|
|
// Take the max index represented
|
2020-04-23 23:16:04 +00:00
|
|
|
idx = lib.MaxUint64(idx, svcIdx)
|
2019-03-21 16:01:56 +00:00
|
|
|
if svcCh != nil {
|
|
|
|
// Watch the service-specific index for changes in liu of all iradix nodes
|
|
|
|
// for checks etc.
|
|
|
|
ws.Add(svcCh)
|
|
|
|
} else {
|
|
|
|
// Nil svcCh shouldn't really happen since all existent services should
|
|
|
|
// have a service-specific index but just in case it does due to a bug,
|
|
|
|
// fall back to the more expensive old way of watching every radix node
|
|
|
|
// we touch.
|
|
|
|
watchOptimized = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// If we have no results, we should use the index of the last service
|
2020-05-08 14:03:45 +00:00
|
|
|
// extinction event so we don't go backwards when services deregister. We
|
2019-03-21 16:01:56 +00:00
|
|
|
// use target serviceName here but it actually doesn't matter. No chan will
|
|
|
|
// be returned as we can't use the optimization in this case (and don't need
|
|
|
|
// to as there is only one chan to watch anyway).
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
svcIdx, _ := maxIndexAndWatchChForService(tx, serviceName, false, true, entMeta, peerName)
|
2020-04-23 23:16:04 +00:00
|
|
|
idx = lib.MaxUint64(idx, svcIdx)
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
|
2019-03-15 20:18:48 +00:00
|
|
|
// Create a nil watchset to pass below, we'll only pass the real one if we
|
|
|
|
// need to. Nil watchers are safe/allowed and saves some allocation too.
|
|
|
|
var fallbackWS memdb.WatchSet
|
2019-03-21 16:01:56 +00:00
|
|
|
if !watchOptimized {
|
|
|
|
// We weren't able to use the optimization of watching only service indexes
|
|
|
|
// for some reason. That means we need to fallback to watching everything we
|
|
|
|
// touch in the DB as normal. We plumb the caller's watchset through (note
|
|
|
|
// it's a map so this is a by-reference assignment.)
|
2019-03-15 20:18:48 +00:00
|
|
|
fallbackWS = ws
|
|
|
|
// We also need to watch the iterator from earlier too.
|
|
|
|
fallbackWS.Add(iter.WatchCh())
|
2019-03-21 16:01:56 +00:00
|
|
|
} else if connect {
|
|
|
|
// If this is a connect query then there is a subtlety to watch out for.
|
|
|
|
// In addition to watching the proxy service indexes for changes above, we
|
|
|
|
// need to still keep an eye on the connect service index in case a new
|
|
|
|
// proxy with a new name registers - we are only watching proxy service
|
|
|
|
// names we know about above so we'd miss that otherwise. Thankfully this
|
|
|
|
// is only ever one extra chan to watch and will catch any changes to
|
|
|
|
// proxy registrations for this target service.
|
|
|
|
ws.Add(iter.WatchCh())
|
2019-03-15 20:18:48 +00:00
|
|
|
}
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return parseCheckServiceNodes(tx, fallbackWS, idx, results, entMeta, peerName, err)
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// CheckServiceTagNodes is used to query all nodes and checks for a given
|
2017-01-16 18:28:46 +00:00
|
|
|
// service, filtering out services that don't contain the given tag.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) CheckServiceTagNodes(ws memdb.WatchSet, serviceName string, tags []string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
2021-03-26 21:21:38 +00:00
|
|
|
// TODO: accept non-pointer value
|
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-03-26 21:21:38 +00:00
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{Value: serviceName, EnterpriseMeta: *entMeta, PeerName: peerName}
|
2021-03-26 21:21:38 +00:00
|
|
|
iter, err := tx.Get(tableServices, indexService, q)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed service lookup: %s", err)
|
|
|
|
}
|
2017-01-24 07:37:21 +00:00
|
|
|
ws.Add(iter.WatchCh())
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// Return the results, filtering by tag.
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
serviceExists := false
|
2017-01-13 19:47:16 +00:00
|
|
|
var results structs.ServiceNodes
|
2017-01-24 07:37:21 +00:00
|
|
|
for service := iter.Next(); service != nil; service = iter.Next() {
|
2017-01-13 19:47:16 +00:00
|
|
|
svc := service.(*structs.ServiceNode)
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
serviceExists = true
|
2018-10-11 11:50:05 +00:00
|
|
|
if !serviceTagsFilter(svc, tags) {
|
2017-01-13 19:47:16 +00:00
|
|
|
results = append(results, svc)
|
|
|
|
}
|
|
|
|
}
|
Improve blocking queries on services that do not exist (#4810)
## Background
When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated.
On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests.
## Implementation
While reducing the number of unnecessary updates we still want :
* Clients to be notified as soon as when the last instance of a service disapears.
* Clients to be notified whenever there's there is an update for the service.
* Clients to be notified as soon as the first instance of the requested service is added.
To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case :
1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42
2. `foo` is unregistered
3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo`
We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly.
We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist.
When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them.
1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42`
2. `foo` is unregistered, we set the "missing service index" to 43
3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43`
4. `client1` makes a blocking query for `foo` with `index=43` -> we block
5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked
6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query
2019-01-11 14:26:14 +00:00
|
|
|
|
|
|
|
// Get the table index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := maxIndexForService(tx, serviceName, serviceExists, true, entMeta, peerName)
|
|
|
|
return parseCheckServiceNodes(tx, ws, idx, results, entMeta, peerName, err)
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
2020-04-16 21:00:48 +00:00
|
|
|
// GatewayServices is used to query all services associated with a gateway
|
2022-04-05 21:10:06 +00:00
|
|
|
func (s *Store) GatewayServices(ws memdb.WatchSet, gateway string, entMeta *acl.EnterpriseMeta) (uint64, structs.GatewayServices, error) {
|
2020-04-08 18:37:24 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
2021-03-16 17:54:05 +00:00
|
|
|
iter, err := tx.Get(tableGatewayServices, indexGateway, structs.NewServiceName(gateway, entMeta))
|
2020-04-08 18:37:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed gateway services lookup: %s", err)
|
|
|
|
}
|
|
|
|
ws.Add(iter.WatchCh())
|
|
|
|
|
2020-07-31 19:30:40 +00:00
|
|
|
maxIdx, results, err := s.collectGatewayServices(tx, ws, iter)
|
2020-08-10 23:48:22 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, err
|
|
|
|
}
|
2021-01-29 01:48:51 +00:00
|
|
|
idx := maxIndexTxn(tx, tableGatewayServices)
|
2020-07-31 19:30:40 +00:00
|
|
|
|
2020-04-23 23:16:04 +00:00
|
|
|
return lib.MaxUint64(maxIdx, idx), results, nil
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
|
|
|
|
2022-07-14 18:45:51 +00:00
|
|
|
// TODO: Find a way to consolidate this with CheckIngressServiceNodes
|
|
|
|
// ServiceGateways is used to query all gateways associated with a service
|
|
|
|
func (s *Store) ServiceGateways(ws memdb.WatchSet, service string, kind structs.ServiceKind, entMeta acl.EnterpriseMeta) (uint64, structs.CheckServiceNodes, error) {
|
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
|
|
|
// tableGatewayServices is not peer-aware, and the existence of TG/IG gateways is scrubbed during peer replication.
|
|
|
|
maxIdx, nodes, err := serviceGatewayNodes(tx, ws, service, kind, &entMeta, structs.DefaultPeerKeyword)
|
|
|
|
|
|
|
|
// Watch for index changes to the gateway nodes
|
|
|
|
idx, chans := maxIndexAndWatchChsForServiceNodes(tx, nodes, false)
|
|
|
|
for _, ch := range chans {
|
|
|
|
ws.Add(ch)
|
|
|
|
}
|
|
|
|
maxIdx = lib.MaxUint64(maxIdx, idx)
|
|
|
|
|
|
|
|
return parseCheckServiceNodes(tx, ws, maxIdx, nodes, &entMeta, structs.DefaultPeerKeyword, err)
|
|
|
|
}
|
|
|
|
|
2022-06-24 18:38:39 +00:00
|
|
|
func (s *Store) VirtualIPForService(psn structs.PeeredServiceName) (string, error) {
|
2021-12-02 23:42:47 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
2022-06-24 18:38:39 +00:00
|
|
|
vip, err := tx.First(tableServiceVirtualIPs, indexID, psn)
|
2021-12-02 23:42:47 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("failed service virtual IP lookup: %s", err)
|
|
|
|
}
|
|
|
|
if vip == nil {
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
result, err := addIPOffset(startingVirtualIP, vip.(ServiceVirtualIP).IP)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return result.String(), nil
|
|
|
|
}
|
|
|
|
|
2022-06-29 20:34:58 +00:00
|
|
|
// VirtualIPsForAllImportedServices returns a slice of ServiceVirtualIP for all
|
|
|
|
// VirtualIP-assignable services that have been imported by the partition represented in entMeta.
|
|
|
|
// Namespace is ignored.
|
|
|
|
func (s *Store) VirtualIPsForAllImportedServices(ws memdb.WatchSet, entMeta acl.EnterpriseMeta) (uint64, []ServiceVirtualIP, error) {
|
|
|
|
tx := s.db.ReadTxn()
|
|
|
|
defer tx.Abort()
|
|
|
|
|
|
|
|
q := Query{
|
|
|
|
EnterpriseMeta: entMeta,
|
|
|
|
// Wildcard peername is used by prefix index to fetch all remote peers for a partition.
|
|
|
|
PeerName: "*",
|
|
|
|
}
|
|
|
|
iter, err := tx.Get(tableServiceVirtualIPs, indexID+"_prefix", q)
|
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed service virtual IP lookup: %s", err)
|
|
|
|
}
|
|
|
|
ws.Add(iter.WatchCh())
|
|
|
|
|
|
|
|
idx := maxIndexTxn(tx, partitionedIndexEntryName(tableServiceVirtualIPs+".imported", entMeta.PartitionOrDefault()))
|
|
|
|
|
|
|
|
var vips []ServiceVirtualIP
|
|
|
|
for raw := iter.Next(); raw != nil; raw = iter.Next() {
|
|
|
|
vip := raw.(ServiceVirtualIP)
|
|
|
|
vips = append(vips, vip)
|
|
|
|
}
|
|
|
|
|
|
|
|
return idx, vips, nil
|
|
|
|
}
|
|
|
|
|
2021-12-02 16:06:39 +00:00
|
|
|
func (s *Store) ServiceNamesOfKind(ws memdb.WatchSet, kind structs.ServiceKind) (uint64, []*KindServiceName, error) {
|
2021-12-02 00:44:13 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
wildcardMeta := structs.WildcardEnterpriseMetaInPartition(structs.WildcardSpecifier)
|
|
|
|
return serviceNamesOfKindTxn(tx, ws, kind, *wildcardMeta)
|
2021-12-02 16:06:39 +00:00
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func serviceNamesOfKindTxn(tx ReadTxn, ws memdb.WatchSet, kind structs.ServiceKind, entMeta acl.EnterpriseMeta) (uint64, []*KindServiceName, error) {
|
|
|
|
iter, err := tx.Get(tableKindServiceNames, indexKind, Query{Value: string(kind), EnterpriseMeta: entMeta})
|
2021-12-02 00:44:13 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, err
|
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
|
|
|
|
// TODO(peering): Maybe delete this watch and rely on the max idx tables below, to avoid waking up on unrelated changes
|
2021-12-02 00:44:13 +00:00
|
|
|
ws.Add(iter.WatchCh())
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
var names []*KindServiceName
|
2021-12-02 00:44:13 +00:00
|
|
|
for name := iter.Next(); name != nil; name = iter.Next() {
|
|
|
|
ksn := name.(*KindServiceName)
|
|
|
|
names = append(names, ksn)
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
var idx uint64
|
|
|
|
switch {
|
|
|
|
case entMeta.PartitionOrDefault() == structs.WildcardSpecifier:
|
|
|
|
idx = kindServiceNamesMaxIndex(tx, ws, kind.Normalized())
|
|
|
|
|
|
|
|
case entMeta.NamespaceOrDefault() == structs.WildcardSpecifier:
|
|
|
|
idx = kindServiceNamesMaxIndex(tx, ws, partitionedIndexEntryName(kind.Normalized(), entMeta.PartitionOrDefault()))
|
|
|
|
|
|
|
|
default:
|
|
|
|
idx = kindServiceNamesMaxIndex(tx, ws, partitionedAndNamespacedIndexEntryName(kind.Normalized(), &entMeta))
|
|
|
|
|
|
|
|
}
|
2021-12-02 00:44:13 +00:00
|
|
|
return idx, names, nil
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// parseCheckServiceNodes is used to parse through a given set of services,
|
|
|
|
// and query for an associated node and a set of checks. This is the inner
|
|
|
|
// method used to return a rich set of results from a more simple query.
|
2020-11-14 00:25:28 +00:00
|
|
|
//
|
|
|
|
// TODO: idx parameter is not used except as a return value. Remove it.
|
|
|
|
// TODO: err parameter is only used for early return. Remove it and check from the
|
|
|
|
// caller.
|
2020-07-10 00:56:43 +00:00
|
|
|
func parseCheckServiceNodes(
|
2020-09-03 23:38:03 +00:00
|
|
|
tx ReadTxn, ws memdb.WatchSet, idx uint64,
|
2020-06-23 17:18:22 +00:00
|
|
|
services structs.ServiceNodes,
|
2022-04-05 21:10:06 +00:00
|
|
|
entMeta *acl.EnterpriseMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
peerName string,
|
|
|
|
err error,
|
|
|
|
) (uint64, structs.CheckServiceNodes, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Special-case the zero return value to nil, since this ends up in
|
|
|
|
// external APIs.
|
|
|
|
if len(services) == 0 {
|
|
|
|
return idx, nil, nil
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
|
|
|
|
2017-01-24 07:37:21 +00:00
|
|
|
// We don't want to track an unlimited number of nodes, so we pull a
|
|
|
|
// top-level watch to use as a fallback.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
allNodes, err := tx.Get(tableNodes, indexID+"_prefix", Query{
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
})
|
2017-01-24 07:37:21 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed nodes lookup: %s", err)
|
|
|
|
}
|
|
|
|
allNodesCh := allNodes.WatchCh()
|
|
|
|
|
|
|
|
// We need a similar fallback for checks. Since services need the
|
|
|
|
// status of node + service-specific checks, we pull in a top-level
|
|
|
|
// watch over all checks.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
allChecks, err := tx.Get(tableChecks, indexID+"_prefix", Query{
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
})
|
2017-01-24 07:37:21 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed checks lookup: %s", err)
|
|
|
|
}
|
|
|
|
allChecksCh := allChecks.WatchCh()
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
results := make(structs.CheckServiceNodes, 0, len(services))
|
|
|
|
for _, sn := range services {
|
|
|
|
// Retrieve the node.
|
2021-08-17 18:29:39 +00:00
|
|
|
watchCh, n, err := tx.FirstWatch(tableNodes, indexID, Query{
|
|
|
|
Value: sn.Node,
|
|
|
|
EnterpriseMeta: sn.EnterpriseMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: sn.PeerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed node lookup: %s", err)
|
|
|
|
}
|
2017-01-24 07:37:21 +00:00
|
|
|
ws.AddWithLimit(watchLimit, watchCh, allNodesCh)
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
if n == nil {
|
|
|
|
return 0, nil, ErrMissingNode
|
|
|
|
}
|
|
|
|
node := n.(*structs.Node)
|
|
|
|
|
2017-01-24 07:37:21 +00:00
|
|
|
// First add the node-level checks. These always apply to any
|
|
|
|
// service on the node.
|
2017-01-13 19:47:16 +00:00
|
|
|
var checks structs.HealthChecks
|
2021-08-17 18:29:39 +00:00
|
|
|
q := NodeServiceQuery{
|
|
|
|
Node: sn.Node,
|
|
|
|
Service: "", // node checks have no service
|
2021-09-17 23:36:20 +00:00
|
|
|
EnterpriseMeta: *sn.EnterpriseMeta.WithWildcardNamespace(),
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: sn.PeerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
}
|
2021-02-11 00:40:32 +00:00
|
|
|
iter, err := tx.Get(tableChecks, indexNodeService, q)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, err
|
|
|
|
}
|
2017-01-24 07:37:21 +00:00
|
|
|
ws.AddWithLimit(watchLimit, iter.WatchCh(), allChecksCh)
|
2017-01-13 19:47:16 +00:00
|
|
|
for check := iter.Next(); check != nil; check = iter.Next() {
|
2017-01-24 07:37:21 +00:00
|
|
|
checks = append(checks, check.(*structs.HealthCheck))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now add the service-specific checks.
|
2021-08-17 18:29:39 +00:00
|
|
|
q = NodeServiceQuery{
|
|
|
|
Node: sn.Node,
|
|
|
|
Service: sn.ServiceID,
|
|
|
|
EnterpriseMeta: sn.EnterpriseMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: sn.PeerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
}
|
2021-02-11 00:40:32 +00:00
|
|
|
iter, err = tx.Get(tableChecks, indexNodeService, q)
|
2017-01-24 07:37:21 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, err
|
|
|
|
}
|
|
|
|
ws.AddWithLimit(watchLimit, iter.WatchCh(), allChecksCh)
|
|
|
|
for check := iter.Next(); check != nil; check = iter.Next() {
|
|
|
|
checks = append(checks, check.(*structs.HealthCheck))
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Append to the results.
|
|
|
|
results = append(results, structs.CheckServiceNode{
|
|
|
|
Node: node,
|
|
|
|
Service: sn.ToNodeService(),
|
|
|
|
Checks: checks,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return idx, results, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// NodeInfo is used to generate a dump of a single node. The dump includes
|
|
|
|
// all services and checks which are registered against the node.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) NodeInfo(ws memdb.WatchSet, node string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.NodeDump, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
2021-08-17 18:29:39 +00:00
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.NodeEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// Get the table index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogMaxIndex(tx, entMeta, peerName, true)
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// Query the node by the passed node
|
2021-08-17 18:29:39 +00:00
|
|
|
nodes, err := tx.Get(tableNodes, indexID, Query{
|
|
|
|
Value: node,
|
|
|
|
EnterpriseMeta: *entMeta,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: peerName,
|
2021-08-17 18:29:39 +00:00
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed node lookup: %s", err)
|
|
|
|
}
|
2017-01-24 17:06:51 +00:00
|
|
|
ws.Add(nodes.WatchCh())
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return parseNodes(tx, ws, idx, nodes, entMeta, peerName)
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NodeDump is used to generate a dump of all nodes. This call is expensive
|
|
|
|
// as it has to query every node, service, and check. The response can also
|
|
|
|
// be quite large since there is currently no filtering applied.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) NodeDump(ws memdb.WatchSet, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.NodeDump, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.NodeEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// Get the table index.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogMaxIndex(tx, entMeta, peerName, true)
|
2017-01-13 19:47:16 +00:00
|
|
|
|
|
|
|
// Fetch all of the registered nodes
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
}
|
|
|
|
nodes, err := tx.Get(tableNodes, indexID+"_prefix", q)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed node lookup: %s", err)
|
|
|
|
}
|
2017-01-24 17:06:51 +00:00
|
|
|
ws.Add(nodes.WatchCh())
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return parseNodes(tx, ws, idx, nodes, entMeta, peerName)
|
2017-01-13 19:47:16 +00:00
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) ServiceDump(ws memdb.WatchSet, kind structs.ServiceKind, useKind bool, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error) {
|
2019-04-16 16:00:15 +00:00
|
|
|
tx := s.db.Txn(false)
|
|
|
|
defer tx.Abort()
|
|
|
|
|
2019-06-20 19:04:39 +00:00
|
|
|
if useKind {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return serviceDumpKindTxn(tx, ws, kind, entMeta, peerName)
|
2019-06-20 19:04:39 +00:00
|
|
|
} else {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return serviceDumpAllTxn(tx, ws, entMeta, peerName)
|
2019-06-20 19:04:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func serviceDumpAllTxn(tx ReadTxn, ws memdb.WatchSet, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error) {
|
2019-04-16 16:00:15 +00:00
|
|
|
// Get the table index
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogMaxIndexWatch(tx, ws, entMeta, "", true)
|
2019-04-16 16:00:15 +00:00
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if entMeta == nil {
|
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
|
|
|
}
|
|
|
|
|
|
|
|
q := Query{
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
}
|
|
|
|
services, err := tx.Get(tableServices, indexID+"_prefix", q)
|
2019-04-16 16:00:15 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed service lookup: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var results structs.ServiceNodes
|
|
|
|
for service := services.Next(); service != nil; service = services.Next() {
|
|
|
|
sn := service.(*structs.ServiceNode)
|
|
|
|
results = append(results, sn)
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return parseCheckServiceNodes(tx, nil, idx, results, entMeta, peerName, err)
|
2019-06-20 19:04:39 +00:00
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func serviceDumpKindTxn(tx ReadTxn, ws memdb.WatchSet, kind structs.ServiceKind, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error) {
|
2019-06-20 19:04:39 +00:00
|
|
|
// unlike when we are dumping all services here we only need to watch the kind specific index entry for changing (or nodes, checks)
|
|
|
|
// updating any services, nodes or checks will bump the appropriate service kind index so there is no need to watch any of the individual
|
|
|
|
// entries
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx := catalogServiceKindMaxIndex(tx, ws, kind, entMeta, peerName)
|
2019-06-20 19:04:39 +00:00
|
|
|
|
2021-03-26 22:38:52 +00:00
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-03-26 22:38:52 +00:00
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
Value: string(kind),
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
}
|
2021-03-26 22:38:52 +00:00
|
|
|
services, err := tx.Get(tableServices, indexKind, q)
|
2019-06-20 19:04:39 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed service lookup: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var results structs.ServiceNodes
|
|
|
|
for service := services.Next(); service != nil; service = services.Next() {
|
|
|
|
sn := service.(*structs.ServiceNode)
|
|
|
|
results = append(results, sn)
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return parseCheckServiceNodes(tx, nil, idx, results, entMeta, peerName, err)
|
2019-04-16 16:00:15 +00:00
|
|
|
}
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
// parseNodes takes an iterator over a set of nodes and returns a struct
|
|
|
|
// containing the nodes along with all of their associated services
|
|
|
|
// and/or health checks.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
// TODO(peering): support parsing by peerName
|
2020-09-03 23:38:03 +00:00
|
|
|
func parseNodes(tx ReadTxn, ws memdb.WatchSet, idx uint64,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
iter memdb.ResultIterator, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.NodeDump, error) {
|
2017-01-13 19:47:16 +00:00
|
|
|
|
2021-02-12 22:31:02 +00:00
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-02-12 22:31:02 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 17:06:51 +00:00
|
|
|
// We don't want to track an unlimited number of services, so we pull a
|
|
|
|
// top-level watch to use as a fallback.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: peerName,
|
|
|
|
}
|
|
|
|
allServices, err := tx.Get(tableServices, indexID+"_prefix", q)
|
2017-01-24 17:06:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed services lookup: %s", err)
|
|
|
|
}
|
|
|
|
allServicesCh := allServices.WatchCh()
|
|
|
|
|
|
|
|
// We need a similar fallback for checks.
|
2021-08-17 18:29:39 +00:00
|
|
|
allChecks, err := tx.Get(tableChecks, indexID+"_prefix", entMeta)
|
2017-01-24 17:06:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed checks lookup: %s", err)
|
|
|
|
}
|
|
|
|
allChecksCh := allChecks.WatchCh()
|
|
|
|
|
2017-01-13 19:47:16 +00:00
|
|
|
var results structs.NodeDump
|
|
|
|
for n := iter.Next(); n != nil; n = iter.Next() {
|
|
|
|
node := n.(*structs.Node)
|
|
|
|
|
|
|
|
// Create the wrapped node
|
|
|
|
dump := &structs.NodeInfo{
|
2017-01-18 22:26:42 +00:00
|
|
|
ID: node.ID,
|
2017-01-13 19:47:16 +00:00
|
|
|
Node: node.Node,
|
2021-08-17 18:29:39 +00:00
|
|
|
Partition: node.Partition,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: node.PeerName,
|
2017-01-13 19:47:16 +00:00
|
|
|
Address: node.Address,
|
|
|
|
TaggedAddresses: node.TaggedAddresses,
|
|
|
|
Meta: node.Meta,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Query the node services
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
services, err := catalogServiceListByNode(tx, node.Node, entMeta, node.PeerName, true)
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed services lookup: %s", err)
|
|
|
|
}
|
2017-01-24 17:06:51 +00:00
|
|
|
ws.AddWithLimit(watchLimit, services.WatchCh(), allServicesCh)
|
2017-01-13 19:47:16 +00:00
|
|
|
for service := services.Next(); service != nil; service = services.Next() {
|
|
|
|
ns := service.(*structs.ServiceNode).ToNodeService()
|
|
|
|
dump.Services = append(dump.Services, ns)
|
|
|
|
}
|
|
|
|
|
2019-12-10 02:26:41 +00:00
|
|
|
// Query the service level checks
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
checks, err := catalogListChecksByNode(tx, Query{
|
|
|
|
Value: node.Node,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: node.PeerName,
|
|
|
|
})
|
2017-01-13 19:47:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed node lookup: %s", err)
|
|
|
|
}
|
2017-01-24 17:06:51 +00:00
|
|
|
ws.AddWithLimit(watchLimit, checks.WatchCh(), allChecksCh)
|
2017-01-13 19:47:16 +00:00
|
|
|
for check := checks.Next(); check != nil; check = checks.Next() {
|
|
|
|
hc := check.(*structs.HealthCheck)
|
|
|
|
dump.Checks = append(dump.Checks, hc)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the result to the slice
|
|
|
|
results = append(results, dump)
|
|
|
|
}
|
|
|
|
return idx, results, nil
|
|
|
|
}
|
2019-12-10 02:26:41 +00:00
|
|
|
|
|
|
|
// checkSessionsTxn returns the IDs of all sessions associated with a health check
|
2020-09-03 23:38:03 +00:00
|
|
|
func checkSessionsTxn(tx ReadTxn, hc *structs.HealthCheck) ([]*sessionCheck, error) {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
// TODO(peering): what are implications for imported health checks?
|
2021-11-24 14:10:38 +00:00
|
|
|
mappings, err := tx.Get(tableSessionChecks, indexNodeCheck, MultiQuery{Value: []string{hc.Node, string(hc.CheckID)},
|
2021-12-03 20:36:07 +00:00
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMetaInPartition(hc.PartitionOrDefault())})
|
2019-12-10 02:26:41 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed session checks lookup: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var sessions []*sessionCheck
|
|
|
|
for mapping := mappings.Next(); mapping != nil; mapping = mappings.Next() {
|
|
|
|
sessions = append(sessions, mapping.(*sessionCheck))
|
|
|
|
}
|
|
|
|
return sessions, nil
|
|
|
|
}
|
2020-04-08 18:37:24 +00:00
|
|
|
|
2020-04-16 21:00:48 +00:00
|
|
|
// updateGatewayServices associates services with gateways as specified in a gateway config entry
|
2022-04-05 21:10:06 +00:00
|
|
|
func updateGatewayServices(tx WriteTxn, idx uint64, conf structs.ConfigEntry, entMeta *acl.EnterpriseMeta) error {
|
2020-05-11 17:38:04 +00:00
|
|
|
var (
|
|
|
|
noChange bool
|
|
|
|
gatewayServices structs.GatewayServices
|
|
|
|
err error
|
|
|
|
)
|
2020-04-08 18:37:24 +00:00
|
|
|
|
2020-06-12 14:57:41 +00:00
|
|
|
gateway := structs.NewServiceName(conf.GetName(), entMeta)
|
2020-04-16 21:00:48 +00:00
|
|
|
switch conf.GetKind() {
|
|
|
|
case structs.IngressGateway:
|
2020-07-10 00:56:43 +00:00
|
|
|
noChange, gatewayServices, err = ingressConfigGatewayServices(tx, gateway, conf, entMeta)
|
2020-04-16 21:00:48 +00:00
|
|
|
case structs.TerminatingGateway:
|
2020-07-10 00:56:43 +00:00
|
|
|
noChange, gatewayServices, err = terminatingConfigGatewayServices(tx, gateway, conf, entMeta)
|
2020-04-16 21:00:48 +00:00
|
|
|
default:
|
|
|
|
return fmt.Errorf("config entry kind %q does not need gateway-services", conf.GetKind())
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
2020-04-16 21:00:48 +00:00
|
|
|
// Return early if there is an error OR we don't have any services to update
|
2020-05-11 17:38:04 +00:00
|
|
|
if err != nil || noChange {
|
2020-04-16 21:00:48 +00:00
|
|
|
return err
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
|
|
|
|
2022-01-12 20:08:49 +00:00
|
|
|
// Update terminating gateway service virtual IPs
|
|
|
|
vipsSupported, err := terminatingGatewayVirtualIPsSupported(tx, nil)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if vipsSupported && conf.GetKind() == structs.TerminatingGateway {
|
|
|
|
gatewayConf := conf.(*structs.TerminatingGatewayConfigEntry)
|
|
|
|
if err := updateTerminatingGatewayVirtualIPs(tx, idx, gatewayConf, entMeta); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-08 18:37:24 +00:00
|
|
|
// Delete all associated with gateway first, to avoid keeping mappings that were removed
|
2020-10-08 15:47:09 +00:00
|
|
|
sn := structs.NewServiceName(conf.GetName(), entMeta)
|
|
|
|
|
2021-03-16 17:54:05 +00:00
|
|
|
if _, err := tx.DeleteAll(tableGatewayServices, indexGateway, sn); err != nil {
|
2020-04-08 18:37:24 +00:00
|
|
|
return fmt.Errorf("failed to truncate gateway services table: %v", err)
|
|
|
|
}
|
2020-10-08 15:47:09 +00:00
|
|
|
if err := truncateGatewayServiceTopologyMappings(tx, idx, sn, conf.GetKind()); err != nil {
|
|
|
|
return fmt.Errorf("failed to truncate mesh topology for gateway: %v", err)
|
|
|
|
}
|
2020-04-08 18:37:24 +00:00
|
|
|
|
2020-04-16 21:00:48 +00:00
|
|
|
for _, svc := range gatewayServices {
|
2020-04-08 18:37:24 +00:00
|
|
|
// If the service is a wildcard we need to target all services within the namespace
|
2020-06-12 14:57:41 +00:00
|
|
|
if svc.Service.Name == structs.WildcardSpecifier {
|
2020-07-10 00:56:43 +00:00
|
|
|
if err := updateGatewayNamespace(tx, idx, svc, entMeta); err != nil {
|
2020-06-12 14:57:41 +00:00
|
|
|
return fmt.Errorf("failed to associate gateway %q with wildcard: %v", gateway.String(), err)
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
|
|
|
// Skip service-specific update below if there was a wildcard update
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Since this service was specified on its own, and not with a wildcard,
|
|
|
|
// if there is an existing entry, we overwrite it. The service entry is the source of truth.
|
|
|
|
//
|
|
|
|
// By extension, if TLS creds are provided with a wildcard but are not provided in
|
|
|
|
// the service entry, the service does not inherit the creds from the wildcard.
|
2020-07-10 00:56:43 +00:00
|
|
|
err = updateGatewayService(tx, idx, svc)
|
2020-04-16 21:00:48 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-29 01:48:51 +00:00
|
|
|
if err := indexUpdateMaxTxn(tx, idx, tableGatewayServices); err != nil {
|
2020-04-16 21:00:48 +00:00
|
|
|
return fmt.Errorf("failed updating gateway-services index: %v", err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-06-29 20:34:58 +00:00
|
|
|
func getTermGatewayVirtualIPs(
|
|
|
|
tx WriteTxn,
|
|
|
|
idx uint64,
|
|
|
|
services []structs.LinkedService,
|
|
|
|
entMeta *acl.EnterpriseMeta,
|
|
|
|
) (map[string]structs.ServiceAddress, error) {
|
2022-01-12 20:08:49 +00:00
|
|
|
addrs := make(map[string]structs.ServiceAddress, len(services))
|
|
|
|
for _, s := range services {
|
|
|
|
sn := structs.ServiceName{Name: s.Name, EnterpriseMeta: *entMeta}
|
2022-06-24 18:38:39 +00:00
|
|
|
// Terminating Gateways cannot route to services in peered clusters
|
|
|
|
psn := structs.PeeredServiceName{ServiceName: sn, Peer: structs.DefaultPeerKeyword}
|
2022-06-29 20:34:58 +00:00
|
|
|
vip, err := assignServiceVirtualIP(tx, idx, psn)
|
2022-01-12 20:08:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
key := structs.ServiceGatewayVirtualIPTag(sn)
|
|
|
|
addrs[key] = structs.ServiceAddress{Address: vip}
|
|
|
|
}
|
|
|
|
|
|
|
|
return addrs, nil
|
|
|
|
}
|
|
|
|
|
2022-04-05 21:10:06 +00:00
|
|
|
func updateTerminatingGatewayVirtualIPs(tx WriteTxn, idx uint64, conf *structs.TerminatingGatewayConfigEntry, entMeta *acl.EnterpriseMeta) error {
|
2022-01-12 20:08:49 +00:00
|
|
|
// Build the current map of services with virtual IPs for this gateway
|
|
|
|
services := conf.Services
|
2022-06-29 20:34:58 +00:00
|
|
|
addrs, err := getTermGatewayVirtualIPs(tx, idx, services, entMeta)
|
2022-01-12 20:08:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find any deleted service entries by comparing the new config entry to the existing one.
|
|
|
|
_, existing, err := configEntryTxn(tx, nil, conf.GetKind(), conf.GetName(), entMeta)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to get config entry: %v", err)
|
|
|
|
}
|
|
|
|
var deletes []structs.ServiceName
|
|
|
|
cfg, ok := existing.(*structs.TerminatingGatewayConfigEntry)
|
|
|
|
if ok {
|
|
|
|
for _, s := range cfg.Services {
|
|
|
|
sn := structs.ServiceName{Name: s.Name, EnterpriseMeta: *entMeta}
|
|
|
|
key := structs.ServiceGatewayVirtualIPTag(sn)
|
|
|
|
if _, ok := addrs[key]; !ok {
|
|
|
|
deletes = append(deletes, sn)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
q := Query{Value: conf.GetName(), EnterpriseMeta: *entMeta}
|
|
|
|
_, svcNodes, err := serviceNodesTxn(tx, nil, indexService, q)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the tagged addrs for any existing instances of this terminating gateway.
|
|
|
|
for _, s := range svcNodes {
|
|
|
|
newAddrs := make(map[string]structs.ServiceAddress)
|
|
|
|
for key, addr := range s.ServiceTaggedAddresses {
|
|
|
|
if !strings.HasPrefix(key, structs.TaggedAddressVirtualIP+":") {
|
|
|
|
newAddrs[key] = addr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for key, addr := range addrs {
|
|
|
|
newAddrs[key] = addr
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't need to update the service record if it's a no-op.
|
|
|
|
if reflect.DeepEqual(newAddrs, s.ServiceTaggedAddresses) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
newSN := s.PartialClone()
|
|
|
|
newSN.ServiceTaggedAddresses = newAddrs
|
|
|
|
newSN.ModifyIndex = idx
|
|
|
|
if err := catalogInsertService(tx, newSN); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if we can delete any virtual IPs for the removed services.
|
|
|
|
gatewayName := structs.NewServiceName(conf.GetName(), entMeta)
|
|
|
|
for _, sn := range deletes {
|
|
|
|
// If there's no existing service nodes, attempt to free the virtual IP.
|
|
|
|
q := Query{Value: sn.Name, EnterpriseMeta: sn.EnterpriseMeta}
|
|
|
|
_, nodes, err := serviceNodesTxn(tx, nil, indexConnect, q)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if len(nodes) == 0 {
|
2022-06-24 18:38:39 +00:00
|
|
|
psn := structs.PeeredServiceName{Peer: structs.DefaultPeerKeyword, ServiceName: sn}
|
2022-07-21 12:38:28 +00:00
|
|
|
if err := freeServiceVirtualIP(tx, idx, psn, &gatewayName); err != nil {
|
2022-01-12 20:08:49 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-05-11 19:04:59 +00:00
|
|
|
// ingressConfigGatewayServices constructs a list of GatewayService structs for
|
|
|
|
// insertion into the memdb table, specific to ingress gateways. The boolean
|
|
|
|
// returned indicates that there are no changes necessary to the memdb table.
|
2020-07-10 00:56:43 +00:00
|
|
|
func ingressConfigGatewayServices(
|
2020-09-03 23:38:03 +00:00
|
|
|
tx ReadTxn,
|
2020-06-12 14:57:41 +00:00
|
|
|
gateway structs.ServiceName,
|
2020-05-11 19:04:59 +00:00
|
|
|
conf structs.ConfigEntry,
|
2022-04-05 21:10:06 +00:00
|
|
|
entMeta *acl.EnterpriseMeta,
|
2020-05-11 19:04:59 +00:00
|
|
|
) (bool, structs.GatewayServices, error) {
|
2020-04-16 21:00:48 +00:00
|
|
|
entry, ok := conf.(*structs.IngressGatewayConfigEntry)
|
|
|
|
if !ok {
|
2020-05-11 17:38:04 +00:00
|
|
|
return false, nil, fmt.Errorf("unexpected config entry type: %T", conf)
|
2020-04-16 21:00:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check if service list matches the last known list for the config entry, if it does, skip the update
|
2020-07-10 00:56:43 +00:00
|
|
|
_, c, err := configEntryTxn(tx, nil, conf.GetKind(), conf.GetName(), entMeta)
|
2020-04-16 21:00:48 +00:00
|
|
|
if err != nil {
|
2020-05-11 17:38:04 +00:00
|
|
|
return false, nil, fmt.Errorf("failed to get config entry: %v", err)
|
2020-04-16 21:00:48 +00:00
|
|
|
}
|
|
|
|
if cfg, ok := c.(*structs.IngressGatewayConfigEntry); ok && cfg != nil {
|
|
|
|
if reflect.DeepEqual(cfg.Listeners, entry.Listeners) {
|
|
|
|
// Services are the same, nothing to update
|
2020-05-11 17:38:04 +00:00
|
|
|
return true, nil, nil
|
2020-04-16 21:00:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var gatewayServices structs.GatewayServices
|
|
|
|
for _, listener := range entry.Listeners {
|
|
|
|
for _, service := range listener.Services {
|
|
|
|
mapping := &structs.GatewayService{
|
|
|
|
Gateway: gateway,
|
2020-06-12 14:57:41 +00:00
|
|
|
Service: service.ToServiceName(),
|
2020-04-16 21:00:48 +00:00
|
|
|
GatewayKind: structs.ServiceKindIngressGateway,
|
2020-04-23 15:06:19 +00:00
|
|
|
Hosts: service.Hosts,
|
2020-04-16 21:00:48 +00:00
|
|
|
Port: listener.Port,
|
2020-04-16 23:24:11 +00:00
|
|
|
Protocol: listener.Protocol,
|
2020-04-16 21:00:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gatewayServices = append(gatewayServices, mapping)
|
|
|
|
}
|
|
|
|
}
|
2020-05-11 17:38:04 +00:00
|
|
|
return false, gatewayServices, nil
|
2020-04-16 21:00:48 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 19:04:59 +00:00
|
|
|
// terminatingConfigGatewayServices constructs a list of GatewayService structs
|
|
|
|
// for insertion into the memdb table, specific to terminating gateways. The
|
|
|
|
// boolean returned indicates that there are no changes necessary to the memdb
|
|
|
|
// table.
|
2020-07-10 00:56:43 +00:00
|
|
|
func terminatingConfigGatewayServices(
|
2020-09-03 23:38:03 +00:00
|
|
|
tx ReadTxn,
|
2020-06-12 14:57:41 +00:00
|
|
|
gateway structs.ServiceName,
|
2020-05-11 19:04:59 +00:00
|
|
|
conf structs.ConfigEntry,
|
2022-04-05 21:10:06 +00:00
|
|
|
entMeta *acl.EnterpriseMeta,
|
2020-05-11 19:04:59 +00:00
|
|
|
) (bool, structs.GatewayServices, error) {
|
2020-04-16 21:00:48 +00:00
|
|
|
entry, ok := conf.(*structs.TerminatingGatewayConfigEntry)
|
|
|
|
if !ok {
|
2020-05-11 17:38:04 +00:00
|
|
|
return false, nil, fmt.Errorf("unexpected config entry type: %T", conf)
|
2020-04-16 21:00:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check if service list matches the last known list for the config entry, if it does, skip the update
|
2020-07-10 00:56:43 +00:00
|
|
|
_, c, err := configEntryTxn(tx, nil, conf.GetKind(), conf.GetName(), entMeta)
|
2020-04-16 21:00:48 +00:00
|
|
|
if err != nil {
|
2020-05-11 17:38:04 +00:00
|
|
|
return false, nil, fmt.Errorf("failed to get config entry: %v", err)
|
2020-04-16 21:00:48 +00:00
|
|
|
}
|
|
|
|
if cfg, ok := c.(*structs.TerminatingGatewayConfigEntry); ok && cfg != nil {
|
|
|
|
if reflect.DeepEqual(cfg.Services, entry.Services) {
|
|
|
|
// Services are the same, nothing to update
|
2020-05-11 17:38:04 +00:00
|
|
|
return true, nil, nil
|
2020-04-16 21:00:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var gatewayServices structs.GatewayServices
|
|
|
|
for _, svc := range entry.Services {
|
2022-05-31 20:20:12 +00:00
|
|
|
kind, err := GatewayServiceKind(tx, svc.Name, &svc.EnterpriseMeta)
|
|
|
|
if err != nil {
|
|
|
|
return false, nil, fmt.Errorf("failed to get gateway service kind for service %s: %v", svc.Name, err)
|
|
|
|
}
|
2020-04-08 18:37:24 +00:00
|
|
|
mapping := &structs.GatewayService{
|
2020-04-16 21:00:48 +00:00
|
|
|
Gateway: gateway,
|
2020-06-12 14:57:41 +00:00
|
|
|
Service: structs.NewServiceName(svc.Name, &svc.EnterpriseMeta),
|
2020-04-08 18:37:24 +00:00
|
|
|
GatewayKind: structs.ServiceKindTerminatingGateway,
|
|
|
|
KeyFile: svc.KeyFile,
|
|
|
|
CertFile: svc.CertFile,
|
|
|
|
CAFile: svc.CAFile,
|
2020-04-27 22:25:37 +00:00
|
|
|
SNI: svc.SNI,
|
2022-05-31 20:20:12 +00:00
|
|
|
ServiceKind: kind,
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
|
|
|
|
2020-04-16 21:00:48 +00:00
|
|
|
gatewayServices = append(gatewayServices, mapping)
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
2020-05-11 17:38:04 +00:00
|
|
|
return false, gatewayServices, nil
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
|
|
|
|
2022-05-31 20:20:12 +00:00
|
|
|
func GatewayServiceKind(tx ReadTxn, name string, entMeta *acl.EnterpriseMeta) (structs.GatewayServiceKind, error) {
|
|
|
|
serviceIter, err := tx.First(tableServices, indexService, Query{
|
|
|
|
Value: name,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return structs.GatewayServiceKindUnknown, err
|
|
|
|
}
|
|
|
|
if serviceIter != nil {
|
|
|
|
return structs.GatewayServiceKindService, err
|
|
|
|
}
|
|
|
|
|
|
|
|
_, entry, err := configEntryTxn(tx, nil, structs.ServiceDefaults, name, entMeta)
|
|
|
|
if err != nil {
|
|
|
|
return structs.GatewayServiceKindUnknown, err
|
|
|
|
}
|
|
|
|
if entry != nil {
|
|
|
|
sd, ok := entry.(*structs.ServiceConfigEntry)
|
|
|
|
if !ok {
|
|
|
|
return structs.GatewayServiceKindUnknown, fmt.Errorf("invalid config entry type %T", entry)
|
|
|
|
}
|
|
|
|
if sd.Destination != nil {
|
|
|
|
return structs.GatewayServiceKindDestination, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return structs.GatewayServiceKindUnknown, nil
|
|
|
|
}
|
|
|
|
|
2020-04-16 21:00:48 +00:00
|
|
|
// updateGatewayNamespace is used to target all services within a namespace
|
2022-04-05 21:10:06 +00:00
|
|
|
func updateGatewayNamespace(tx WriteTxn, idx uint64, service *structs.GatewayService, entMeta *acl.EnterpriseMeta) error {
|
2021-03-26 22:38:52 +00:00
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-03-26 22:38:52 +00:00
|
|
|
}
|
|
|
|
q := Query{Value: string(structs.ServiceKindTypical), EnterpriseMeta: *entMeta}
|
|
|
|
services, err := tx.Get(tableServices, indexKind, q)
|
2020-04-08 18:37:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed querying services: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterate over services in namespace and insert mapping for each
|
|
|
|
for svc := services.Next(); svc != nil; svc = services.Next() {
|
|
|
|
sn := svc.(*structs.ServiceNode)
|
|
|
|
|
|
|
|
// Only associate non-consul services with gateways
|
|
|
|
if sn.ServiceName == "consul" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2022-08-08 17:44:18 +00:00
|
|
|
hasConnectInstance, hasNonConnectInstance, err := serviceHasConnectInstances(tx, sn.ServiceName, entMeta)
|
2022-07-28 19:51:01 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-08-08 17:44:18 +00:00
|
|
|
if service.GatewayKind == structs.ServiceKindIngressGateway && !hasConnectInstance {
|
2022-07-28 19:51:01 +00:00
|
|
|
continue
|
|
|
|
}
|
2022-08-08 17:44:18 +00:00
|
|
|
if service.GatewayKind == structs.ServiceKindTerminatingGateway && !hasNonConnectInstance {
|
2022-07-28 19:51:01 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-03-16 18:20:11 +00:00
|
|
|
existing, err := tx.First(tableGatewayServices, indexID, service.Gateway, sn.CompoundServiceName(), service.Port)
|
2020-04-08 18:37:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("gateway service lookup failed: %s", err)
|
|
|
|
}
|
2020-04-16 21:00:48 +00:00
|
|
|
if existing != nil {
|
2020-04-08 18:37:24 +00:00
|
|
|
// If there's an existing service associated with this gateway then we skip it.
|
|
|
|
// This means the service was specified on its own, and the service entry overrides the wildcard entry.
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2020-04-16 21:00:48 +00:00
|
|
|
mapping := service.Clone()
|
2020-04-17 00:51:27 +00:00
|
|
|
|
2020-06-12 14:57:41 +00:00
|
|
|
mapping.Service = structs.NewServiceName(sn.ServiceName, &service.Service.EnterpriseMeta)
|
2020-04-17 00:51:27 +00:00
|
|
|
mapping.FromWildcard = true
|
|
|
|
|
2020-07-10 00:56:43 +00:00
|
|
|
err = updateGatewayService(tx, idx, mapping)
|
2020-04-16 21:00:48 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-31 20:20:12 +00:00
|
|
|
entries, err := tx.Get(tableConfigEntries, indexID+"_prefix", ConfigEntryKindQuery{Kind: structs.ServiceDefaults, EnterpriseMeta: *entMeta})
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed querying entries: %s", err)
|
|
|
|
}
|
|
|
|
for entry := entries.Next(); entry != nil; entry = entries.Next() {
|
|
|
|
e := entry.(*structs.ServiceConfigEntry)
|
|
|
|
if e.Destination == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
sn := structs.ServiceName{
|
|
|
|
Name: e.Name,
|
|
|
|
EnterpriseMeta: e.EnterpriseMeta,
|
|
|
|
}
|
|
|
|
existing, err := tx.First(tableGatewayServices, indexID, service.Gateway, sn, service.Port)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("gateway service lookup failed: %s", err)
|
|
|
|
}
|
|
|
|
if existing != nil {
|
|
|
|
// If there's an existing service associated with this gateway then we skip it.
|
|
|
|
// This means the service was specified on its own, and the service entry overrides the wildcard entry.
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
mapping := service.Clone()
|
|
|
|
|
|
|
|
mapping.Service = structs.NewServiceName(e.Name, &service.Service.EnterpriseMeta)
|
|
|
|
mapping.ServiceKind = structs.GatewayServiceKindDestination
|
|
|
|
mapping.FromWildcard = true
|
|
|
|
|
|
|
|
err = updateGatewayService(tx, idx, mapping)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2020-04-08 18:37:24 +00:00
|
|
|
|
|
|
|
// Also store a mapping for the wildcard so that the TLS creds can be pulled
|
|
|
|
// for new services registered in its namespace
|
2020-07-10 00:56:43 +00:00
|
|
|
err = updateGatewayService(tx, idx, service)
|
2020-04-16 21:00:48 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-08-02 16:41:19 +00:00
|
|
|
// serviceHasConnectInstances returns whether the service has at least one connect instance,
|
2022-07-28 19:51:01 +00:00
|
|
|
// and at least one non-connect instance.
|
2022-08-02 16:41:19 +00:00
|
|
|
func serviceHasConnectInstances(tx WriteTxn, serviceName string, entMeta *acl.EnterpriseMeta) (bool, bool, error) {
|
2022-07-28 19:51:01 +00:00
|
|
|
hasConnectInstance := false
|
2022-08-02 16:41:19 +00:00
|
|
|
query := Query{
|
2022-07-28 19:51:01 +00:00
|
|
|
Value: serviceName,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
}
|
2022-08-02 16:41:19 +00:00
|
|
|
svc, err := tx.First(tableServices, indexConnect, query)
|
2022-07-28 19:51:01 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, false, fmt.Errorf("failed service lookup: %s", err)
|
|
|
|
}
|
|
|
|
if svc != nil {
|
|
|
|
hasConnectInstance = true
|
|
|
|
}
|
|
|
|
|
|
|
|
hasNonConnectInstance := false
|
2022-08-02 16:41:19 +00:00
|
|
|
iter, err := tx.Get(tableServices, indexService, query)
|
2022-07-28 19:51:01 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, false, fmt.Errorf("failed service lookup: %s", err)
|
|
|
|
}
|
|
|
|
for service := iter.Next(); service != nil; service = iter.Next() {
|
|
|
|
sn := service.(*structs.ServiceNode)
|
|
|
|
if !sn.ServiceConnect.Native {
|
|
|
|
hasNonConnectInstance = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hasConnectInstance, hasNonConnectInstance, nil
|
|
|
|
}
|
|
|
|
|
2023-02-21 19:59:36 +00:00
|
|
|
// serviceHasConnectEnabledInstances returns whether the given service name
|
|
|
|
// has a corresponding connect-proxy or connect-native instance.
|
|
|
|
// This function is mostly a clone of `serviceHasConnectInstances`, but it has
|
|
|
|
// an early return to improve performance and returns true if at least one
|
|
|
|
// connect-native instance exists.
|
|
|
|
func serviceHasConnectEnabledInstances(tx WriteTxn, serviceName string, entMeta *acl.EnterpriseMeta) (bool, error) {
|
|
|
|
query := Query{
|
|
|
|
Value: serviceName,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
}
|
|
|
|
|
|
|
|
svc, err := tx.First(tableServices, indexConnect, query)
|
|
|
|
if err != nil {
|
|
|
|
return false, fmt.Errorf("failed service lookup: %w", err)
|
|
|
|
}
|
|
|
|
if svc != nil {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
2020-04-08 18:37:24 +00:00
|
|
|
// updateGatewayService associates services with gateways after an eligible event
|
|
|
|
// ie. Registering a service in a namespace targeted by a gateway
|
2020-09-03 23:38:03 +00:00
|
|
|
func updateGatewayService(tx WriteTxn, idx uint64, mapping *structs.GatewayService) error {
|
2020-04-08 18:37:24 +00:00
|
|
|
// Check if mapping already exists in table if it's already in the table
|
|
|
|
// Avoid insert if nothing changed
|
2021-03-16 18:20:11 +00:00
|
|
|
existing, err := tx.First(tableGatewayServices, indexID, mapping.Gateway, mapping.Service, mapping.Port)
|
2020-04-08 18:37:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("gateway service lookup failed: %s", err)
|
|
|
|
}
|
|
|
|
if gs, ok := existing.(*structs.GatewayService); ok && gs != nil {
|
2020-04-16 21:00:48 +00:00
|
|
|
mapping.CreateIndex = gs.CreateIndex
|
2020-04-08 18:37:24 +00:00
|
|
|
if gs.IsSame(mapping) {
|
|
|
|
return nil
|
|
|
|
}
|
2020-04-16 21:00:48 +00:00
|
|
|
} else {
|
|
|
|
// We have a new mapping
|
|
|
|
mapping.CreateIndex = idx
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
2020-04-16 21:00:48 +00:00
|
|
|
mapping.ModifyIndex = idx
|
2020-04-08 18:37:24 +00:00
|
|
|
|
2021-01-29 01:48:51 +00:00
|
|
|
if err := tx.Insert(tableGatewayServices, mapping); err != nil {
|
2020-04-08 18:37:24 +00:00
|
|
|
return fmt.Errorf("failed inserting gateway service mapping: %s", err)
|
|
|
|
}
|
|
|
|
|
2021-01-29 01:48:51 +00:00
|
|
|
if err := indexUpdateMaxTxn(tx, idx, tableGatewayServices); err != nil {
|
2020-04-16 21:00:48 +00:00
|
|
|
return fmt.Errorf("failed updating gateway-services index: %v", err)
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
2020-10-08 15:47:09 +00:00
|
|
|
|
|
|
|
if err := insertGatewayServiceTopologyMapping(tx, idx, mapping); err != nil {
|
|
|
|
return fmt.Errorf("failed to reconcile mesh topology for gateway: %v", err)
|
|
|
|
}
|
2020-04-08 18:37:24 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-04-17 16:24:34 +00:00
|
|
|
// checkWildcardForGatewaysAndUpdate checks whether a service matches a
|
|
|
|
// wildcard definition in gateway config entries and if so adds it the the
|
|
|
|
// gateway-services table.
|
2022-07-28 19:51:01 +00:00
|
|
|
func checkGatewayWildcardsAndUpdate(tx WriteTxn, idx uint64, svc *structs.ServiceName, ns *structs.NodeService, kind structs.GatewayServiceKind) error {
|
2021-03-16 17:54:05 +00:00
|
|
|
sn := structs.ServiceName{Name: structs.WildcardSpecifier, EnterpriseMeta: svc.EnterpriseMeta}
|
|
|
|
svcGateways, err := tx.Get(tableGatewayServices, indexService, sn)
|
2020-04-17 16:24:34 +00:00
|
|
|
if err != nil {
|
2022-05-31 20:20:12 +00:00
|
|
|
return fmt.Errorf("failed gateway lookup for %q: %s", svc.Name, err)
|
2020-04-17 16:24:34 +00:00
|
|
|
}
|
2022-07-28 19:51:01 +00:00
|
|
|
|
2022-08-02 16:41:19 +00:00
|
|
|
hasConnectInstance, hasNonConnectInstance, err := serviceHasConnectInstances(tx, svc.Name, &svc.EnterpriseMeta)
|
2022-07-28 19:51:01 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-08-02 16:41:19 +00:00
|
|
|
// If we were passed a NodeService, this might be the first registered instance of the service
|
|
|
|
// so we need to count it as either a connect or non-connect instance.
|
|
|
|
if ns != nil {
|
|
|
|
if ns.Connect.Native || ns.Kind == structs.ServiceKindConnectProxy {
|
|
|
|
hasConnectInstance = true
|
|
|
|
} else {
|
|
|
|
hasNonConnectInstance = true
|
|
|
|
}
|
2022-07-28 19:51:01 +00:00
|
|
|
}
|
|
|
|
|
2020-04-17 16:24:34 +00:00
|
|
|
for service := svcGateways.Next(); service != nil; service = svcGateways.Next() {
|
|
|
|
if wildcardSvc, ok := service.(*structs.GatewayService); ok && wildcardSvc != nil {
|
2022-08-02 16:41:19 +00:00
|
|
|
if wildcardSvc.GatewayKind == structs.ServiceKindIngressGateway && !hasConnectInstance {
|
2022-07-28 19:51:01 +00:00
|
|
|
continue
|
|
|
|
}
|
2022-08-02 16:41:19 +00:00
|
|
|
if wildcardSvc.GatewayKind == structs.ServiceKindTerminatingGateway && !hasNonConnectInstance && kind != structs.GatewayServiceKindDestination {
|
2022-07-28 19:51:01 +00:00
|
|
|
continue
|
|
|
|
}
|
2020-04-17 16:24:34 +00:00
|
|
|
|
|
|
|
// Copy the wildcard mapping and modify it
|
|
|
|
gatewaySvc := wildcardSvc.Clone()
|
2020-04-17 00:51:27 +00:00
|
|
|
|
2022-05-31 20:20:12 +00:00
|
|
|
gatewaySvc.Service = structs.NewServiceName(svc.Name, &svc.EnterpriseMeta)
|
2020-04-17 00:51:27 +00:00
|
|
|
gatewaySvc.FromWildcard = true
|
2022-05-31 20:20:12 +00:00
|
|
|
gatewaySvc.ServiceKind = kind
|
2020-04-17 16:24:34 +00:00
|
|
|
|
2020-07-10 00:56:43 +00:00
|
|
|
if err = updateGatewayService(tx, idx, gatewaySvc); err != nil {
|
2020-04-17 16:24:34 +00:00
|
|
|
return fmt.Errorf("Failed to associate service %q with gateway %q", gatewaySvc.Service.String(), gatewaySvc.Gateway.String())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-05-31 20:20:12 +00:00
|
|
|
// checkGatewayAndUpdate checks whether a service matches a
|
|
|
|
// wildcard definition in gateway config entries and if so adds it the the
|
|
|
|
// gateway-services table.
|
|
|
|
func checkGatewayAndUpdate(tx WriteTxn, idx uint64, svc *structs.ServiceName, kind structs.GatewayServiceKind) error {
|
|
|
|
sn := structs.ServiceName{Name: svc.Name, EnterpriseMeta: svc.EnterpriseMeta}
|
|
|
|
svcGateways, err := tx.First(tableGatewayServices, indexService, sn)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed gateway lookup for %q: %s", svc.Name, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if service, ok := svcGateways.(*structs.GatewayService); ok && service != nil {
|
|
|
|
// Copy the wildcard mapping and modify it
|
|
|
|
gatewaySvc := service.Clone()
|
|
|
|
|
|
|
|
gatewaySvc.Service = structs.NewServiceName(svc.Name, &svc.EnterpriseMeta)
|
|
|
|
gatewaySvc.ServiceKind = kind
|
|
|
|
|
|
|
|
if err = updateGatewayService(tx, idx, gatewaySvc); err != nil {
|
|
|
|
return fmt.Errorf("Failed to associate service %q with gateway %q", gatewaySvc.Service.String(), gatewaySvc.Gateway.String())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-08-08 17:44:18 +00:00
|
|
|
func cleanupGatewayWildcards(tx WriteTxn, idx uint64, sn structs.ServiceName, cleaningUpDestination bool) error {
|
2020-09-27 18:38:32 +00:00
|
|
|
// Clean up association between service name and gateways if needed
|
2021-03-16 17:54:05 +00:00
|
|
|
gateways, err := tx.Get(tableGatewayServices, indexService, sn)
|
2020-09-27 18:38:32 +00:00
|
|
|
if err != nil {
|
2022-08-08 17:44:18 +00:00
|
|
|
return fmt.Errorf("failed gateway lookup for %q: %s", sn.Name, err)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
2021-01-20 15:17:26 +00:00
|
|
|
|
|
|
|
mappings := make([]*structs.GatewayService, 0)
|
2020-09-27 18:38:32 +00:00
|
|
|
for mapping := gateways.Next(); mapping != nil; mapping = gateways.Next() {
|
|
|
|
if gs, ok := mapping.(*structs.GatewayService); ok && gs != nil {
|
2021-01-20 15:17:26 +00:00
|
|
|
mappings = append(mappings, gs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-28 19:51:01 +00:00
|
|
|
// Check whether there are any connect or non-connect instances remaining for this service.
|
|
|
|
// If there are no connect instances left, ingress gateways with a wildcard entry can remove
|
|
|
|
// their association with it (same with terminating gateways if there are no non-connect
|
|
|
|
// instances left).
|
2022-08-08 17:44:18 +00:00
|
|
|
hasConnectInstance, hasNonConnectInstance, err := serviceHasConnectInstances(tx, sn.Name, &sn.EnterpriseMeta)
|
2022-07-28 19:51:01 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-08-08 17:44:18 +00:00
|
|
|
// If we're deleting a service instance but this service is defined as a destination via config entry,
|
|
|
|
// keep the mapping around.
|
|
|
|
hasDestination := false
|
|
|
|
if !cleaningUpDestination {
|
|
|
|
q := configentry.NewKindName(structs.ServiceDefaults, sn.Name, &sn.EnterpriseMeta)
|
|
|
|
existing, err := tx.First(tableConfigEntries, indexID, q)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed config entry lookup: %s", err)
|
|
|
|
}
|
|
|
|
if existing != nil {
|
|
|
|
if entry, ok := existing.(*structs.ServiceConfigEntry); ok && entry.Destination != nil {
|
|
|
|
hasDestination = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-20 15:17:26 +00:00
|
|
|
// Do the updates in a separate loop so we don't trash the iterator.
|
|
|
|
for _, m := range mappings {
|
|
|
|
// Only delete if association was created by a wildcard specifier.
|
|
|
|
// Otherwise the service was specified in the config entry, and the association should be maintained
|
|
|
|
// for when the service is re-registered
|
|
|
|
if m.FromWildcard {
|
2022-07-28 19:51:01 +00:00
|
|
|
if m.GatewayKind == structs.ServiceKindIngressGateway && hasConnectInstance {
|
|
|
|
continue
|
|
|
|
}
|
2022-08-08 17:44:18 +00:00
|
|
|
if m.GatewayKind == structs.ServiceKindTerminatingGateway && (hasNonConnectInstance || hasDestination) {
|
2022-07-28 19:51:01 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-01-29 01:48:51 +00:00
|
|
|
if err := tx.Delete(tableGatewayServices, m); err != nil {
|
2021-01-20 15:17:26 +00:00
|
|
|
return fmt.Errorf("failed to truncate gateway services table: %v", err)
|
|
|
|
}
|
2021-01-29 01:48:51 +00:00
|
|
|
if err := indexUpdateMaxTxn(tx, idx, tableGatewayServices); err != nil {
|
2021-01-20 15:17:26 +00:00
|
|
|
return fmt.Errorf("failed updating gateway-services index: %v", err)
|
|
|
|
}
|
|
|
|
if err := deleteGatewayServiceTopologyMapping(tx, idx, m); err != nil {
|
|
|
|
return fmt.Errorf("failed to reconcile mesh topology for gateway: %v", err)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
2022-05-31 20:20:12 +00:00
|
|
|
} else {
|
|
|
|
kind, err := GatewayServiceKind(tx, m.Service.Name, &m.Service.EnterpriseMeta)
|
|
|
|
if err != nil {
|
2022-08-08 17:44:18 +00:00
|
|
|
return fmt.Errorf("failed to get gateway service kind for service %s: %v", sn.Name, err)
|
2022-05-31 20:20:12 +00:00
|
|
|
}
|
|
|
|
checkGatewayAndUpdate(tx, idx, &structs.ServiceName{Name: m.Service.Name, EnterpriseMeta: m.Service.EnterpriseMeta}, kind)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-07-30 16:21:11 +00:00
|
|
|
func (s *Store) DumpGatewayServices(ws memdb.WatchSet) (uint64, structs.GatewayServices, error) {
|
|
|
|
tx := s.db.ReadTxn()
|
|
|
|
defer tx.Abort()
|
|
|
|
|
2021-03-16 18:20:11 +00:00
|
|
|
iter, err := tx.Get(tableGatewayServices, indexID)
|
2020-07-30 16:21:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed to dump gateway-services: %s", err)
|
|
|
|
}
|
2020-08-05 22:07:11 +00:00
|
|
|
ws.Add(iter.WatchCh())
|
|
|
|
|
|
|
|
maxIdx, results, err := s.collectGatewayServices(tx, ws, iter)
|
2020-08-10 23:48:22 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, err
|
|
|
|
}
|
2021-01-29 01:48:51 +00:00
|
|
|
idx := maxIndexTxn(tx, tableGatewayServices)
|
2020-07-30 16:21:11 +00:00
|
|
|
|
2020-08-05 22:07:11 +00:00
|
|
|
return lib.MaxUint64(maxIdx, idx), results, nil
|
2020-07-31 19:30:40 +00:00
|
|
|
}
|
|
|
|
|
2020-09-03 23:38:03 +00:00
|
|
|
func (s *Store) collectGatewayServices(tx ReadTxn, ws memdb.WatchSet, iter memdb.ResultIterator) (uint64, structs.GatewayServices, error) {
|
2020-07-30 16:21:11 +00:00
|
|
|
var maxIdx uint64
|
|
|
|
var results structs.GatewayServices
|
|
|
|
|
2020-07-31 19:30:40 +00:00
|
|
|
for obj := iter.Next(); obj != nil; obj = iter.Next() {
|
2020-07-30 16:21:11 +00:00
|
|
|
gs := obj.(*structs.GatewayService)
|
2020-08-05 22:07:11 +00:00
|
|
|
maxIdx = lib.MaxUint64(maxIdx, gs.ModifyIndex)
|
2020-07-30 16:21:11 +00:00
|
|
|
|
|
|
|
if gs.Service.Name != structs.WildcardSpecifier {
|
2020-09-14 22:17:43 +00:00
|
|
|
idx, matches, err := checkProtocolMatch(tx, ws, gs)
|
2020-07-30 16:21:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed checking protocol: %s", err)
|
|
|
|
}
|
|
|
|
maxIdx = lib.MaxUint64(maxIdx, idx)
|
2020-08-05 22:07:11 +00:00
|
|
|
|
2020-07-30 16:21:11 +00:00
|
|
|
if matches {
|
|
|
|
results = append(results, gs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return maxIdx, results, nil
|
|
|
|
}
|
|
|
|
|
2022-07-14 18:45:51 +00:00
|
|
|
// TODO: How to handle index rolling back when a config entry is
|
2020-04-16 21:00:48 +00:00
|
|
|
// deleted that references a service?
|
|
|
|
// We might need something like the service_last_extinction index?
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func serviceGatewayNodes(tx ReadTxn, ws memdb.WatchSet, service string, kind structs.ServiceKind, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.ServiceNodes, error) {
|
|
|
|
if peerName != "" {
|
|
|
|
return 0, nil, nil
|
|
|
|
}
|
|
|
|
|
2020-04-08 18:37:24 +00:00
|
|
|
// Look up gateway name associated with the service
|
2021-03-16 17:54:05 +00:00
|
|
|
gws, err := tx.Get(tableGatewayServices, indexService, structs.NewServiceName(service, entMeta))
|
2020-04-08 18:37:24 +00:00
|
|
|
if err != nil {
|
2020-04-29 22:52:27 +00:00
|
|
|
return 0, nil, fmt.Errorf("failed gateway lookup: %s", err)
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
|
|
|
|
2020-04-16 23:30:31 +00:00
|
|
|
// Adding this channel to the WatchSet means that the watch will fire if a config entry targeting the service is added.
|
|
|
|
// Otherwise, if there's no associated gateway, then no watch channel would be returned
|
|
|
|
ws.Add(gws.WatchCh())
|
|
|
|
|
2020-04-08 18:37:24 +00:00
|
|
|
var ret structs.ServiceNodes
|
2020-04-16 21:00:48 +00:00
|
|
|
var maxIdx uint64
|
2020-04-08 18:37:24 +00:00
|
|
|
|
2020-04-16 21:00:48 +00:00
|
|
|
for gateway := gws.Next(); gateway != nil; gateway = gws.Next() {
|
|
|
|
mapping := gateway.(*structs.GatewayService)
|
|
|
|
// TODO(ingress): Test this conditional
|
|
|
|
if mapping.GatewayKind != kind {
|
|
|
|
continue
|
|
|
|
}
|
2020-04-23 23:16:04 +00:00
|
|
|
maxIdx = lib.MaxUint64(maxIdx, mapping.ModifyIndex)
|
2020-04-08 18:37:24 +00:00
|
|
|
|
|
|
|
// Look up nodes for gateway
|
2021-08-17 18:29:39 +00:00
|
|
|
q := Query{
|
|
|
|
Value: mapping.Gateway.Name,
|
|
|
|
EnterpriseMeta: mapping.Gateway.EnterpriseMeta,
|
|
|
|
}
|
2021-03-26 21:21:38 +00:00
|
|
|
gwServices, err := tx.Get(tableServices, indexService, q)
|
2020-04-08 18:37:24 +00:00
|
|
|
if err != nil {
|
2020-04-29 22:52:27 +00:00
|
|
|
return 0, nil, fmt.Errorf("failed service lookup: %s", err)
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
2020-04-27 22:25:37 +00:00
|
|
|
|
|
|
|
var exists bool
|
2020-04-16 21:00:48 +00:00
|
|
|
for svc := gwServices.Next(); svc != nil; svc = gwServices.Next() {
|
|
|
|
sn := svc.(*structs.ServiceNode)
|
2020-04-08 18:37:24 +00:00
|
|
|
ret = append(ret, sn)
|
2020-04-27 22:25:37 +00:00
|
|
|
|
|
|
|
// Tracking existence to know whether we should check extinction index for service
|
|
|
|
exists = true
|
|
|
|
}
|
|
|
|
|
2020-05-08 15:44:34 +00:00
|
|
|
// This prevents the index from sliding back if case all instances of the gateway service are deregistered
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
svcIdx := maxIndexForService(tx, mapping.Gateway.Name, exists, false, &mapping.Gateway.EnterpriseMeta, structs.DefaultPeerKeyword)
|
2020-04-23 23:16:04 +00:00
|
|
|
maxIdx = lib.MaxUint64(maxIdx, svcIdx)
|
2020-04-27 22:25:37 +00:00
|
|
|
|
2020-04-29 22:52:27 +00:00
|
|
|
// Ensure that blocking queries wake up if the gateway-service mapping exists, but the gateway does not exist yet
|
|
|
|
if !exists {
|
|
|
|
ws.Add(gwServices.WatchCh())
|
|
|
|
}
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
2020-04-29 22:52:27 +00:00
|
|
|
return maxIdx, ret, nil
|
2020-04-08 18:37:24 +00:00
|
|
|
}
|
2020-04-23 23:16:04 +00:00
|
|
|
|
2020-10-08 23:31:54 +00:00
|
|
|
// metricsProtocolForIngressGateway determines the protocol that should be used when fetching metrics for an ingress gateway
|
|
|
|
// Since ingress gateways may have listeners with different protocols, favor capturing all traffic by only returning HTTP
|
|
|
|
// when all listeners are HTTP-like.
|
|
|
|
func metricsProtocolForIngressGateway(tx ReadTxn, ws memdb.WatchSet, sn structs.ServiceName) (uint64, string, error) {
|
|
|
|
idx, conf, err := configEntryTxn(tx, ws, structs.IngressGateway, sn.Name, &sn.EnterpriseMeta)
|
|
|
|
if err != nil {
|
|
|
|
return 0, "", fmt.Errorf("failed to get ingress-gateway config entry for %q: %v", sn.String(), err)
|
|
|
|
}
|
|
|
|
if conf == nil {
|
|
|
|
return 0, "", nil
|
|
|
|
}
|
|
|
|
entry, ok := conf.(*structs.IngressGatewayConfigEntry)
|
|
|
|
if !ok {
|
|
|
|
return 0, "", fmt.Errorf("unexpected config entry type: %T", conf)
|
|
|
|
}
|
|
|
|
counts := make(map[string]int)
|
|
|
|
for _, l := range entry.Listeners {
|
|
|
|
if structs.IsProtocolHTTPLike(l.Protocol) {
|
|
|
|
counts["http"] += 1
|
|
|
|
} else {
|
|
|
|
counts["tcp"] += 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
protocol := "tcp"
|
|
|
|
if counts["tcp"] == 0 && counts["http"] > 0 {
|
|
|
|
protocol = "http"
|
|
|
|
}
|
|
|
|
return idx, protocol, nil
|
|
|
|
}
|
|
|
|
|
2020-04-23 23:16:04 +00:00
|
|
|
// checkProtocolMatch filters out any GatewayService entries added from a wildcard with a protocol
|
|
|
|
// that doesn't match the one configured in their discovery chain.
|
2020-08-11 20:31:23 +00:00
|
|
|
func checkProtocolMatch(tx ReadTxn, ws memdb.WatchSet, svc *structs.GatewayService) (uint64, bool, error) {
|
2020-04-23 23:16:04 +00:00
|
|
|
if svc.GatewayKind != structs.ServiceKindIngressGateway || !svc.FromWildcard {
|
|
|
|
return 0, true, nil
|
|
|
|
}
|
|
|
|
|
2020-07-10 00:56:43 +00:00
|
|
|
idx, protocol, err := protocolForService(tx, ws, svc.Service)
|
2020-04-23 23:16:04 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return idx, svc.Protocol == protocol, nil
|
|
|
|
}
|
2020-09-27 18:38:32 +00:00
|
|
|
|
2021-04-13 16:12:13 +00:00
|
|
|
// TODO(freddy) Split this up. The upstream/downstream logic is very similar.
|
|
|
|
// TODO(freddy) Add comprehensive state store test
|
2020-09-29 01:41:24 +00:00
|
|
|
func (s *Store) ServiceTopology(
|
|
|
|
ws memdb.WatchSet,
|
|
|
|
dc, service string,
|
2020-10-08 23:31:54 +00:00
|
|
|
kind structs.ServiceKind,
|
2020-10-08 00:35:34 +00:00
|
|
|
defaultAllow acl.EnforcementDecision,
|
2022-04-05 21:10:06 +00:00
|
|
|
entMeta *acl.EnterpriseMeta,
|
2020-09-29 01:41:24 +00:00
|
|
|
) (uint64, *structs.ServiceTopology, error) {
|
2020-10-02 00:10:49 +00:00
|
|
|
tx := s.db.ReadTxn()
|
|
|
|
defer tx.Abort()
|
2020-09-29 01:41:24 +00:00
|
|
|
|
2021-04-13 16:12:13 +00:00
|
|
|
sn := structs.NewServiceName(service, entMeta)
|
2020-10-08 23:31:54 +00:00
|
|
|
|
2021-04-13 16:12:13 +00:00
|
|
|
var (
|
|
|
|
maxIdx uint64
|
|
|
|
protocol string
|
|
|
|
err error
|
|
|
|
fullyTransparent bool
|
|
|
|
hasTransparent bool
|
2022-02-16 21:51:54 +00:00
|
|
|
connectNative bool
|
2020-09-29 01:41:24 +00:00
|
|
|
)
|
2020-10-08 23:31:54 +00:00
|
|
|
switch kind {
|
|
|
|
case structs.ServiceKindIngressGateway:
|
|
|
|
maxIdx, protocol, err = metricsProtocolForIngressGateway(tx, ws, sn)
|
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed to fetch protocol for service %s: %v", sn.String(), err)
|
|
|
|
}
|
|
|
|
|
|
|
|
case structs.ServiceKindTypical:
|
|
|
|
maxIdx, protocol, err = protocolForService(tx, ws, sn)
|
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed to fetch protocol for service %s: %v", sn.String(), err)
|
|
|
|
}
|
|
|
|
|
2021-04-13 16:12:13 +00:00
|
|
|
// Fetch connect endpoints for the target service in order to learn if its proxies are configured as
|
|
|
|
// transparent proxies.
|
|
|
|
if entMeta == nil {
|
2021-07-22 18:20:45 +00:00
|
|
|
entMeta = structs.DefaultEnterpriseMetaInDefaultPartition()
|
2021-04-13 16:12:13 +00:00
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
q := Query{
|
|
|
|
Value: service,
|
|
|
|
EnterpriseMeta: *entMeta,
|
|
|
|
PeerName: structs.TODOPeerKeyword,
|
|
|
|
}
|
2021-04-13 16:12:13 +00:00
|
|
|
|
|
|
|
idx, proxies, err := serviceNodesTxn(tx, ws, indexConnect, q)
|
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed to fetch connect endpoints for service %s: %v", sn.String(), err)
|
|
|
|
}
|
|
|
|
if idx > maxIdx {
|
|
|
|
maxIdx = idx
|
|
|
|
}
|
|
|
|
if len(proxies) == 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
fullyTransparent = true
|
|
|
|
for _, proxy := range proxies {
|
|
|
|
switch proxy.ServiceProxy.Mode {
|
|
|
|
case structs.ProxyModeTransparent:
|
|
|
|
hasTransparent = true
|
|
|
|
|
|
|
|
default:
|
|
|
|
// Only consider the target proxy to be transparent when all instances are in that mode.
|
|
|
|
// This is done because the flag is used to display warnings about proxies needing to enable
|
|
|
|
// transparent proxy mode. If ANY instance isn't in the right mode then the warming applies.
|
|
|
|
fullyTransparent = false
|
|
|
|
}
|
2022-02-16 21:51:54 +00:00
|
|
|
if proxy.ServiceConnect.Native {
|
|
|
|
connectNative = true
|
|
|
|
}
|
2021-04-13 16:12:13 +00:00
|
|
|
}
|
|
|
|
|
2020-10-08 23:31:54 +00:00
|
|
|
default:
|
|
|
|
return 0, nil, fmt.Errorf("unsupported kind %q", kind)
|
|
|
|
}
|
|
|
|
|
2020-10-02 16:05:27 +00:00
|
|
|
idx, upstreamNames, err := upstreamsFromRegistrationTxn(tx, ws, sn)
|
2020-10-02 00:10:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, err
|
|
|
|
}
|
|
|
|
if idx > maxIdx {
|
|
|
|
maxIdx = idx
|
|
|
|
}
|
2021-04-13 16:12:13 +00:00
|
|
|
|
2021-08-25 19:20:32 +00:00
|
|
|
var upstreamSources = make(map[string]string)
|
2021-04-13 16:12:13 +00:00
|
|
|
for _, un := range upstreamNames {
|
|
|
|
upstreamSources[un.String()] = structs.TopologySourceRegistration
|
|
|
|
}
|
|
|
|
|
2021-08-25 19:20:32 +00:00
|
|
|
upstreamDecisions := make(map[string]structs.IntentionDecisionSummary)
|
|
|
|
|
2022-02-16 21:51:54 +00:00
|
|
|
// Only transparent proxies / connect native services have upstreams from intentions
|
|
|
|
if hasTransparent || connectNative {
|
2022-06-07 19:55:02 +00:00
|
|
|
idx, intentionUpstreams, err := s.intentionTopologyTxn(tx, ws, sn, false, defaultAllow, structs.IntentionTargetService)
|
2021-08-25 19:20:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, err
|
|
|
|
}
|
|
|
|
if idx > maxIdx {
|
|
|
|
maxIdx = idx
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, svc := range intentionUpstreams {
|
|
|
|
if _, ok := upstreamSources[svc.Name.String()]; ok {
|
|
|
|
// Avoid duplicating entry
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
upstreamDecisions[svc.Name.String()] = svc.Decision
|
|
|
|
upstreamNames = append(upstreamNames, svc.Name)
|
|
|
|
|
|
|
|
var source string
|
|
|
|
switch {
|
|
|
|
case svc.Decision.HasExact:
|
|
|
|
source = structs.TopologySourceSpecificIntention
|
|
|
|
case svc.Decision.DefaultAllow:
|
|
|
|
source = structs.TopologySourceDefaultAllow
|
|
|
|
default:
|
|
|
|
source = structs.TopologySourceWildcardIntention
|
|
|
|
}
|
|
|
|
upstreamSources[svc.Name.String()] = source
|
|
|
|
}
|
2020-09-29 01:41:24 +00:00
|
|
|
}
|
2021-08-25 19:20:32 +00:00
|
|
|
|
|
|
|
matchEntry := structs.IntentionMatchEntry{
|
|
|
|
Namespace: entMeta.NamespaceOrDefault(),
|
2021-09-16 19:31:19 +00:00
|
|
|
Partition: entMeta.PartitionOrDefault(),
|
2021-08-25 19:20:32 +00:00
|
|
|
Name: service,
|
2020-09-29 01:41:24 +00:00
|
|
|
}
|
2022-06-07 19:03:59 +00:00
|
|
|
_, srcIntentions, err := compatIntentionMatchOneTxn(tx, ws, matchEntry, structs.IntentionMatchSource, structs.IntentionTargetService)
|
2021-08-25 19:20:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed to query intentions for %s", sn.String())
|
|
|
|
}
|
2021-04-13 16:12:13 +00:00
|
|
|
|
2021-08-25 19:20:32 +00:00
|
|
|
for _, un := range upstreamNames {
|
2021-09-16 19:31:19 +00:00
|
|
|
opts := IntentionDecisionOpts{
|
|
|
|
Target: un.Name,
|
|
|
|
Namespace: un.NamespaceOrDefault(),
|
|
|
|
Partition: un.PartitionOrDefault(),
|
|
|
|
Intentions: srcIntentions,
|
|
|
|
MatchType: structs.IntentionMatchDestination,
|
|
|
|
DefaultDecision: defaultAllow,
|
|
|
|
AllowPermissions: false,
|
|
|
|
}
|
|
|
|
decision, err := s.IntentionDecision(opts)
|
2021-08-25 19:20:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed to get intention decision from (%s) to (%s): %v",
|
|
|
|
sn.String(), un.String(), err)
|
2021-04-13 16:12:13 +00:00
|
|
|
}
|
2021-08-25 19:20:32 +00:00
|
|
|
upstreamDecisions[un.String()] = decision
|
2021-04-13 16:12:13 +00:00
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx, unfilteredUpstreams, err := s.combinedServiceNodesTxn(tx, ws, upstreamNames, structs.DefaultPeerKeyword)
|
2021-04-13 16:12:13 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed to get upstreams for %q: %v", sn.String(), err)
|
|
|
|
}
|
|
|
|
if idx > maxIdx {
|
|
|
|
maxIdx = idx
|
|
|
|
}
|
|
|
|
|
|
|
|
var upstreams structs.CheckServiceNodes
|
|
|
|
for _, upstream := range unfilteredUpstreams {
|
|
|
|
sn := upstream.Service.CompoundServiceName()
|
|
|
|
if upstream.Service.Kind == structs.ServiceKindConnectProxy {
|
|
|
|
sn = structs.NewServiceName(upstream.Service.Proxy.DestinationServiceName, &upstream.Service.EnterpriseMeta)
|
|
|
|
}
|
|
|
|
|
2022-02-16 21:51:54 +00:00
|
|
|
// Avoid returning upstreams from intentions when none of the proxy instances of the target are in transparent mode or connect native.
|
|
|
|
if !hasTransparent && !connectNative && upstreamSources[sn.String()] != structs.TopologySourceRegistration {
|
2021-04-13 16:12:13 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
upstreams = append(upstreams, upstream)
|
|
|
|
}
|
2020-10-08 00:35:34 +00:00
|
|
|
|
2021-08-25 19:20:32 +00:00
|
|
|
var foundUpstreams = make(map[structs.ServiceName]struct{})
|
|
|
|
for _, csn := range upstreams {
|
|
|
|
foundUpstreams[csn.Service.CompoundServiceName()] = struct{}{}
|
2021-03-13 04:59:47 +00:00
|
|
|
}
|
2021-04-13 16:12:13 +00:00
|
|
|
|
2021-08-25 19:20:32 +00:00
|
|
|
// Check upstream names that had no service instances to see if they are routing config.
|
2020-10-08 00:35:34 +00:00
|
|
|
for _, un := range upstreamNames {
|
2021-08-25 19:20:32 +00:00
|
|
|
if _, ok := foundUpstreams[un]; ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, kind := range serviceGraphKinds {
|
|
|
|
idx, entry, err := configEntryTxn(tx, ws, kind, un.Name, &un.EnterpriseMeta)
|
|
|
|
if err != nil {
|
|
|
|
return 0, nil, err
|
|
|
|
}
|
|
|
|
if entry != nil {
|
|
|
|
upstreamSources[un.String()] = structs.TopologySourceRoutingConfig
|
|
|
|
}
|
|
|
|
if idx > maxIdx {
|
|
|
|
maxIdx = idx
|
|
|
|
}
|
2020-10-08 00:35:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-02 00:10:49 +00:00
|
|
|
idx, downstreamNames, err := s.downstreamsForServiceTxn(tx, ws, dc, sn)
|
|
|
|
if err != nil {
|
|
|
|
return 0, nil, err
|
2020-09-29 01:41:24 +00:00
|
|
|
}
|
2020-10-02 00:10:49 +00:00
|
|
|
if idx > maxIdx {
|
|
|
|
maxIdx = idx
|
|
|
|
}
|
2021-04-13 16:12:13 +00:00
|
|
|
|
2021-08-25 19:20:32 +00:00
|
|
|
var downstreamSources = make(map[string]string)
|
2021-04-13 16:12:13 +00:00
|
|
|
for _, dn := range downstreamNames {
|
|
|
|
downstreamSources[dn.String()] = structs.TopologySourceRegistration
|
|
|
|
}
|
|
|
|
|
2022-06-07 19:55:02 +00:00
|
|
|
idx, intentionDownstreams, err := s.intentionTopologyTxn(tx, ws, sn, true, defaultAllow, structs.IntentionTargetService)
|
2021-04-13 16:12:13 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, err
|
|
|
|
}
|
|
|
|
if idx > maxIdx {
|
|
|
|
maxIdx = idx
|
|
|
|
}
|
|
|
|
|
|
|
|
downstreamDecisions := make(map[string]structs.IntentionDecisionSummary)
|
|
|
|
for _, svc := range intentionDownstreams {
|
2021-08-25 19:20:32 +00:00
|
|
|
if _, ok := downstreamSources[svc.Name.String()]; ok {
|
2021-04-13 16:12:13 +00:00
|
|
|
// Avoid duplicating entry
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
downstreamNames = append(downstreamNames, svc.Name)
|
|
|
|
downstreamDecisions[svc.Name.String()] = svc.Decision
|
|
|
|
|
|
|
|
var source string
|
|
|
|
switch {
|
|
|
|
case svc.Decision.HasExact:
|
|
|
|
source = structs.TopologySourceSpecificIntention
|
|
|
|
case svc.Decision.DefaultAllow:
|
|
|
|
source = structs.TopologySourceDefaultAllow
|
|
|
|
default:
|
|
|
|
source = structs.TopologySourceWildcardIntention
|
|
|
|
}
|
|
|
|
downstreamSources[svc.Name.String()] = source
|
|
|
|
}
|
|
|
|
|
2022-06-07 19:03:59 +00:00
|
|
|
_, dstIntentions, err := compatIntentionMatchOneTxn(tx, ws, matchEntry, structs.IntentionMatchDestination, structs.IntentionTargetService)
|
2021-08-25 19:20:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed to query intentions for %s", sn.String())
|
|
|
|
}
|
|
|
|
for _, dn := range downstreamNames {
|
2021-09-16 19:31:19 +00:00
|
|
|
opts := IntentionDecisionOpts{
|
|
|
|
Target: dn.Name,
|
|
|
|
Namespace: dn.NamespaceOrDefault(),
|
|
|
|
Partition: dn.PartitionOrDefault(),
|
|
|
|
Intentions: dstIntentions,
|
|
|
|
MatchType: structs.IntentionMatchSource,
|
|
|
|
DefaultDecision: defaultAllow,
|
|
|
|
AllowPermissions: false,
|
|
|
|
}
|
|
|
|
decision, err := s.IntentionDecision(opts)
|
2021-08-25 19:20:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed to get intention decision from (%s) to (%s): %v",
|
|
|
|
dn.String(), sn.String(), err)
|
|
|
|
}
|
|
|
|
downstreamDecisions[dn.String()] = decision
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx, unfilteredDownstreams, err := s.combinedServiceNodesTxn(tx, ws, downstreamNames, structs.DefaultPeerKeyword)
|
2022-02-16 21:51:54 +00:00
|
|
|
|
2020-09-29 01:41:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, nil, fmt.Errorf("failed to get downstreams for %q: %v", sn.String(), err)
|
|
|
|
}
|
|
|
|
if idx > maxIdx {
|
|
|
|
maxIdx = idx
|
|
|
|
}
|
|
|
|
|
2021-04-13 16:12:13 +00:00
|
|
|
// Store downstreams with at least one instance in transparent proxy mode.
|
|
|
|
// This is to avoid returning downstreams from intentions when none of the downstreams are transparent proxies.
|
|
|
|
tproxyMap := make(map[structs.ServiceName]struct{})
|
|
|
|
for _, downstream := range unfilteredDownstreams {
|
|
|
|
if downstream.Service.Proxy.Mode == structs.ProxyModeTransparent {
|
|
|
|
sn := structs.NewServiceName(downstream.Service.Proxy.DestinationServiceName, &downstream.Service.EnterpriseMeta)
|
|
|
|
tproxyMap[sn] = struct{}{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var downstreams structs.CheckServiceNodes
|
|
|
|
for _, downstream := range unfilteredDownstreams {
|
|
|
|
sn := downstream.Service.CompoundServiceName()
|
|
|
|
if downstream.Service.Kind == structs.ServiceKindConnectProxy {
|
|
|
|
sn = structs.NewServiceName(downstream.Service.Proxy.DestinationServiceName, &downstream.Service.EnterpriseMeta)
|
|
|
|
}
|
2022-02-16 21:51:54 +00:00
|
|
|
if _, ok := tproxyMap[sn]; !ok && !downstream.Service.Connect.Native && downstreamSources[sn.String()] != structs.TopologySourceRegistration {
|
|
|
|
// If downstream is not a transparent proxy or connect native, remove references
|
2021-08-25 19:20:32 +00:00
|
|
|
delete(downstreamSources, sn.String())
|
|
|
|
delete(downstreamDecisions, sn.String())
|
2021-04-13 16:12:13 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
downstreams = append(downstreams, downstream)
|
|
|
|
}
|
|
|
|
|
2020-10-02 00:10:49 +00:00
|
|
|
resp := &structs.ServiceTopology{
|
2021-04-13 16:12:13 +00:00
|
|
|
TransparentProxy: fullyTransparent,
|
2020-10-08 23:31:54 +00:00
|
|
|
MetricsProtocol: protocol,
|
2020-10-08 00:35:34 +00:00
|
|
|
Upstreams: upstreams,
|
|
|
|
Downstreams: downstreams,
|
|
|
|
UpstreamDecisions: upstreamDecisions,
|
|
|
|
DownstreamDecisions: downstreamDecisions,
|
2021-04-13 16:12:13 +00:00
|
|
|
UpstreamSources: upstreamSources,
|
|
|
|
DownstreamSources: downstreamSources,
|
2020-10-02 00:10:49 +00:00
|
|
|
}
|
|
|
|
return maxIdx, resp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// combinedServiceNodesTxn returns typical and connect endpoints for a list of services.
|
|
|
|
// This enabled aggregating checks statuses across both.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func (s *Store) combinedServiceNodesTxn(tx ReadTxn, ws memdb.WatchSet, names []structs.ServiceName, peerName string) (uint64, structs.CheckServiceNodes, error) {
|
2020-10-02 00:10:49 +00:00
|
|
|
var (
|
|
|
|
maxIdx uint64
|
|
|
|
resp structs.CheckServiceNodes
|
|
|
|
)
|
|
|
|
for _, u := range names {
|
|
|
|
// Collect typical then connect instances
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx, csn, err := checkServiceNodesTxn(tx, ws, u.Name, false, &u.EnterpriseMeta, peerName)
|
2020-09-29 01:41:24 +00:00
|
|
|
if err != nil {
|
2020-10-02 00:10:49 +00:00
|
|
|
return 0, nil, err
|
2020-09-29 01:41:24 +00:00
|
|
|
}
|
|
|
|
if idx > maxIdx {
|
|
|
|
maxIdx = idx
|
|
|
|
}
|
2020-10-02 00:10:49 +00:00
|
|
|
resp = append(resp, csn...)
|
2020-09-29 01:41:24 +00:00
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
idx, csn, err = checkServiceNodesTxn(tx, ws, u.Name, true, &u.EnterpriseMeta, peerName)
|
2020-09-29 01:41:24 +00:00
|
|
|
if err != nil {
|
2020-10-02 00:10:49 +00:00
|
|
|
return 0, nil, err
|
2020-09-29 01:41:24 +00:00
|
|
|
}
|
|
|
|
if idx > maxIdx {
|
|
|
|
maxIdx = idx
|
|
|
|
}
|
2020-10-02 00:10:49 +00:00
|
|
|
resp = append(resp, csn...)
|
2020-09-29 01:41:24 +00:00
|
|
|
}
|
2020-10-02 00:10:49 +00:00
|
|
|
return maxIdx, resp, nil
|
2020-09-29 01:41:24 +00:00
|
|
|
}
|
|
|
|
|
2020-10-02 00:10:49 +00:00
|
|
|
// downstreamsForServiceTxn will find all downstream services that could route traffic to the input service.
|
2020-09-27 20:24:42 +00:00
|
|
|
// There are two factors at play. Upstreams defined in a proxy registration, and the discovery chain for those upstreams.
|
2020-10-02 00:10:49 +00:00
|
|
|
func (s *Store) downstreamsForServiceTxn(tx ReadTxn, ws memdb.WatchSet, dc string, service structs.ServiceName) (uint64, []structs.ServiceName, error) {
|
|
|
|
// First fetch services that have discovery chains that eventually route to the target service
|
|
|
|
idx, sources, err := s.discoveryChainSourcesTxn(tx, ws, dc, service)
|
2020-09-27 20:24:42 +00:00
|
|
|
if err != nil {
|
2020-09-29 01:41:24 +00:00
|
|
|
return 0, nil, fmt.Errorf("failed to get sources for discovery chain target %q: %v", service.String(), err)
|
2020-09-27 20:24:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var maxIdx uint64
|
|
|
|
if idx > maxIdx {
|
|
|
|
maxIdx = idx
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
resp []structs.ServiceName
|
|
|
|
seen = make(map[structs.ServiceName]bool)
|
|
|
|
)
|
|
|
|
for _, s := range sources {
|
2020-10-02 00:10:49 +00:00
|
|
|
// We then follow these sources one level down to the services defining them as an upstream.
|
|
|
|
idx, downstreams, err := downstreamsFromRegistrationTxn(tx, ws, s)
|
2020-09-27 20:24:42 +00:00
|
|
|
if err != nil {
|
2020-09-29 01:41:24 +00:00
|
|
|
return 0, nil, fmt.Errorf("failed to get registration downstreams for %q: %v", s.String(), err)
|
2020-09-27 20:24:42 +00:00
|
|
|
}
|
|
|
|
if idx > maxIdx {
|
|
|
|
maxIdx = idx
|
|
|
|
}
|
|
|
|
for _, d := range downstreams {
|
|
|
|
if !seen[d] {
|
|
|
|
resp = append(resp, d)
|
|
|
|
seen[d] = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return maxIdx, resp, nil
|
|
|
|
}
|
|
|
|
|
2020-10-02 00:10:49 +00:00
|
|
|
// upstreamsFromRegistrationTxn returns the ServiceNames of the upstreams defined across instances of the input
|
|
|
|
func upstreamsFromRegistrationTxn(tx ReadTxn, ws memdb.WatchSet, sn structs.ServiceName) (uint64, []structs.ServiceName, error) {
|
|
|
|
return linkedFromRegistrationTxn(tx, ws, sn, false)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
|
|
|
|
2020-10-02 00:10:49 +00:00
|
|
|
// downstreamsFromRegistrationTxn returns the ServiceNames of downstream services based on registrations across instances of the input
|
|
|
|
func downstreamsFromRegistrationTxn(tx ReadTxn, ws memdb.WatchSet, sn structs.ServiceName) (uint64, []structs.ServiceName, error) {
|
|
|
|
return linkedFromRegistrationTxn(tx, ws, sn, true)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
|
|
|
|
2020-10-02 00:10:49 +00:00
|
|
|
func linkedFromRegistrationTxn(tx ReadTxn, ws memdb.WatchSet, service structs.ServiceName, downstreams bool) (uint64, []structs.ServiceName, error) {
|
2020-09-27 18:38:32 +00:00
|
|
|
// To fetch upstreams we query services that have the input listed as a downstream
|
|
|
|
// To fetch downstreams we query services that have the input listed as an upstream
|
2021-03-16 17:15:14 +00:00
|
|
|
index := indexDownstream
|
2020-09-27 18:38:32 +00:00
|
|
|
if downstreams {
|
2021-03-16 17:15:14 +00:00
|
|
|
index = indexUpstream
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
|
|
|
|
2021-01-29 01:48:51 +00:00
|
|
|
iter, err := tx.Get(tableMeshTopology, index, service)
|
2020-09-27 18:38:32 +00:00
|
|
|
if err != nil {
|
2021-01-29 01:48:51 +00:00
|
|
|
return 0, nil, fmt.Errorf("%q lookup failed: %v", tableMeshTopology, err)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
|
|
|
ws.Add(iter.WatchCh())
|
|
|
|
|
|
|
|
var (
|
|
|
|
idx uint64
|
|
|
|
resp []structs.ServiceName
|
|
|
|
)
|
|
|
|
for raw := iter.Next(); raw != nil; raw = iter.Next() {
|
2021-03-16 17:37:44 +00:00
|
|
|
entry := raw.(*upstreamDownstream)
|
2020-09-27 18:38:32 +00:00
|
|
|
if entry.ModifyIndex > idx {
|
|
|
|
idx = entry.ModifyIndex
|
|
|
|
}
|
|
|
|
|
|
|
|
linked := entry.Upstream
|
|
|
|
if downstreams {
|
|
|
|
linked = entry.Downstream
|
|
|
|
}
|
|
|
|
resp = append(resp, linked)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO (freddy) This needs a tombstone to avoid the index sliding back on mapping deletion
|
|
|
|
// Using the table index here means that blocking queries will wake up more often than they should
|
2021-01-29 01:48:51 +00:00
|
|
|
tableIdx := maxIndexTxn(tx, tableMeshTopology)
|
2020-09-27 18:38:32 +00:00
|
|
|
if tableIdx > idx {
|
|
|
|
idx = tableIdx
|
|
|
|
}
|
|
|
|
return idx, resp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// updateMeshTopology creates associations between the input service and its upstreams in the topology table
|
2020-09-03 23:38:03 +00:00
|
|
|
func updateMeshTopology(tx WriteTxn, idx uint64, node string, svc *structs.NodeService, existing interface{}) error {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
// TODO(peering): make this peering aware
|
2020-09-27 18:38:32 +00:00
|
|
|
oldUpstreams := make(map[structs.ServiceName]bool)
|
|
|
|
if e, ok := existing.(*structs.ServiceNode); ok {
|
|
|
|
for _, u := range e.ServiceProxy.Upstreams {
|
2022-04-05 21:10:06 +00:00
|
|
|
upstreamMeta := acl.NewEnterpriseMetaWithPartition(e.PartitionOrDefault(), u.DestinationNamespace)
|
2021-09-17 23:24:51 +00:00
|
|
|
sn := structs.NewServiceName(u.DestinationName, &upstreamMeta)
|
2020-09-27 18:38:32 +00:00
|
|
|
|
|
|
|
oldUpstreams[sn] = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Despite the name "destination", this service name is downstream of the proxy
|
|
|
|
downstream := structs.NewServiceName(svc.Proxy.DestinationServiceName, &svc.EnterpriseMeta)
|
|
|
|
inserted := make(map[structs.ServiceName]bool)
|
|
|
|
for _, u := range svc.Proxy.Upstreams {
|
2020-09-27 20:24:42 +00:00
|
|
|
if u.DestinationType == structs.UpstreamDestTypePreparedQuery {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO (freddy): Account for upstream datacenter
|
2022-04-05 21:10:06 +00:00
|
|
|
upstreamMeta := acl.NewEnterpriseMetaWithPartition(svc.PartitionOrDefault(), u.DestinationNamespace)
|
2021-09-17 23:24:51 +00:00
|
|
|
upstream := structs.NewServiceName(u.DestinationName, &upstreamMeta)
|
2020-09-27 18:38:32 +00:00
|
|
|
|
2021-03-16 17:15:14 +00:00
|
|
|
obj, err := tx.First(tableMeshTopology, indexID, upstream, downstream)
|
2020-09-27 18:38:32 +00:00
|
|
|
if err != nil {
|
2021-01-29 01:48:51 +00:00
|
|
|
return fmt.Errorf("%q lookup failed: %v", tableMeshTopology, err)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
|
|
|
sid := svc.CompoundServiceID()
|
|
|
|
uid := structs.UniqueID(node, sid.String())
|
|
|
|
|
2021-03-16 17:37:44 +00:00
|
|
|
var mapping *upstreamDownstream
|
|
|
|
if existing, ok := obj.(*upstreamDownstream); ok {
|
2020-09-27 18:38:32 +00:00
|
|
|
rawCopy, err := copystructure.Copy(existing)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to copy existing topology mapping: %v", err)
|
|
|
|
}
|
2021-03-16 17:37:44 +00:00
|
|
|
mapping, ok = rawCopy.(*upstreamDownstream)
|
2020-09-27 18:38:32 +00:00
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("unexpected topology type %T", rawCopy)
|
|
|
|
}
|
2020-10-02 00:10:49 +00:00
|
|
|
mapping.Refs[uid] = struct{}{}
|
2020-09-27 18:38:32 +00:00
|
|
|
mapping.ModifyIndex = idx
|
|
|
|
|
|
|
|
inserted[upstream] = true
|
|
|
|
}
|
|
|
|
if mapping == nil {
|
2021-03-16 17:37:44 +00:00
|
|
|
mapping = &upstreamDownstream{
|
2020-09-27 18:38:32 +00:00
|
|
|
Upstream: upstream,
|
|
|
|
Downstream: downstream,
|
2020-10-02 00:10:49 +00:00
|
|
|
Refs: map[string]struct{}{uid: {}},
|
2020-09-27 18:38:32 +00:00
|
|
|
RaftIndex: structs.RaftIndex{
|
|
|
|
CreateIndex: idx,
|
|
|
|
ModifyIndex: idx,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2021-01-29 01:48:51 +00:00
|
|
|
if err := tx.Insert(tableMeshTopology, mapping); err != nil {
|
|
|
|
return fmt.Errorf("failed inserting %s mapping: %s", tableMeshTopology, err)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
2021-01-29 01:48:51 +00:00
|
|
|
if err := indexUpdateMaxTxn(tx, idx, tableMeshTopology); err != nil {
|
|
|
|
return fmt.Errorf("failed updating %s index: %v", tableMeshTopology, err)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
|
|
|
inserted[upstream] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
for u := range oldUpstreams {
|
|
|
|
if !inserted[u] {
|
2021-03-16 17:15:14 +00:00
|
|
|
if _, err := tx.DeleteAll(tableMeshTopology, indexID, u, downstream); err != nil {
|
2021-01-29 01:48:51 +00:00
|
|
|
return fmt.Errorf("failed to truncate %s table: %v", tableMeshTopology, err)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
2021-01-29 01:48:51 +00:00
|
|
|
if err := indexUpdateMaxTxn(tx, idx, tableMeshTopology); err != nil {
|
|
|
|
return fmt.Errorf("failed updating %s index: %v", tableMeshTopology, err)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// cleanupMeshTopology removes a service from the mesh topology table
|
|
|
|
// This is only safe to call when there are no more known instances of this proxy
|
2020-09-03 23:38:03 +00:00
|
|
|
func cleanupMeshTopology(tx WriteTxn, idx uint64, service *structs.ServiceNode) error {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
// TODO(peering): make this peering aware?
|
2020-09-27 18:38:32 +00:00
|
|
|
if service.ServiceKind != structs.ServiceKindConnectProxy {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
sn := structs.NewServiceName(service.ServiceProxy.DestinationServiceName, &service.EnterpriseMeta)
|
|
|
|
|
|
|
|
sid := service.CompoundServiceID()
|
|
|
|
uid := structs.UniqueID(service.Node, sid.String())
|
|
|
|
|
2021-03-16 17:15:14 +00:00
|
|
|
iter, err := tx.Get(tableMeshTopology, indexDownstream, sn)
|
2020-09-27 18:38:32 +00:00
|
|
|
if err != nil {
|
2021-01-29 01:48:51 +00:00
|
|
|
return fmt.Errorf("%q lookup failed: %v", tableMeshTopology, err)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
2021-01-20 15:17:26 +00:00
|
|
|
|
2021-03-16 17:37:44 +00:00
|
|
|
mappings := make([]*upstreamDownstream, 0)
|
2020-09-27 18:38:32 +00:00
|
|
|
for raw := iter.Next(); raw != nil; raw = iter.Next() {
|
2021-03-16 17:37:44 +00:00
|
|
|
mappings = append(mappings, raw.(*upstreamDownstream))
|
2021-01-20 15:17:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Do the updates in a separate loop so we don't trash the iterator.
|
|
|
|
for _, m := range mappings {
|
|
|
|
rawCopy, err := copystructure.Copy(m)
|
2020-09-27 18:38:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to copy existing topology mapping: %v", err)
|
|
|
|
}
|
2021-03-16 17:37:44 +00:00
|
|
|
copy, ok := rawCopy.(*upstreamDownstream)
|
2020-09-27 18:38:32 +00:00
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("unexpected topology type %T", rawCopy)
|
|
|
|
}
|
|
|
|
|
2021-01-20 15:17:26 +00:00
|
|
|
// Bail early if there's no reference to the proxy ID we're deleting
|
|
|
|
if _, ok := copy.Refs[uid]; !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
delete(copy.Refs, uid)
|
2020-09-27 18:38:32 +00:00
|
|
|
if len(copy.Refs) == 0 {
|
2021-01-29 01:48:51 +00:00
|
|
|
if err := tx.Delete(tableMeshTopology, m); err != nil {
|
|
|
|
return fmt.Errorf("failed to truncate %s table: %v", tableMeshTopology, err)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
2021-01-29 01:48:51 +00:00
|
|
|
if err := indexUpdateMaxTxn(tx, idx, tableMeshTopology); err != nil {
|
|
|
|
return fmt.Errorf("failed updating %s index: %v", tableMeshTopology, err)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
2021-01-20 15:17:26 +00:00
|
|
|
continue
|
|
|
|
|
|
|
|
}
|
2021-01-29 01:48:51 +00:00
|
|
|
if err := tx.Insert(tableMeshTopology, copy); err != nil {
|
|
|
|
return fmt.Errorf("failed inserting %s mapping: %s", tableMeshTopology, err)
|
2020-09-27 18:38:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2020-10-08 15:47:09 +00:00
|
|
|
|
2020-09-03 23:38:03 +00:00
|
|
|
func insertGatewayServiceTopologyMapping(tx WriteTxn, idx uint64, gs *structs.GatewayService) error {
|
2020-10-08 15:47:09 +00:00
|
|
|
// Only ingress gateways are standalone items in the mesh topology viz
|
|
|
|
if gs.GatewayKind != structs.ServiceKindIngressGateway || gs.Service.Name == structs.WildcardSpecifier {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-03-16 17:37:44 +00:00
|
|
|
mapping := upstreamDownstream{
|
2020-10-08 15:47:09 +00:00
|
|
|
Upstream: gs.Service,
|
|
|
|
Downstream: gs.Gateway,
|
2022-02-04 23:51:32 +00:00
|
|
|
Refs: make(map[string]struct{}),
|
2020-10-08 15:47:09 +00:00
|
|
|
RaftIndex: gs.RaftIndex,
|
|
|
|
}
|
2021-01-29 01:48:51 +00:00
|
|
|
if err := tx.Insert(tableMeshTopology, &mapping); err != nil {
|
|
|
|
return fmt.Errorf("failed inserting %s mapping: %s", tableMeshTopology, err)
|
2020-10-08 15:47:09 +00:00
|
|
|
}
|
2021-01-29 01:48:51 +00:00
|
|
|
if err := indexUpdateMaxTxn(tx, idx, tableMeshTopology); err != nil {
|
|
|
|
return fmt.Errorf("failed updating %s index: %v", tableMeshTopology, err)
|
2020-10-08 15:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-09-03 23:38:03 +00:00
|
|
|
func deleteGatewayServiceTopologyMapping(tx WriteTxn, idx uint64, gs *structs.GatewayService) error {
|
2020-10-08 15:47:09 +00:00
|
|
|
// Only ingress gateways are standalone items in the mesh topology viz
|
|
|
|
if gs.GatewayKind != structs.ServiceKindIngressGateway {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-03-16 17:15:14 +00:00
|
|
|
if _, err := tx.DeleteAll(tableMeshTopology, indexID, gs.Service, gs.Gateway); err != nil {
|
2021-01-29 01:48:51 +00:00
|
|
|
return fmt.Errorf("failed to truncate %s table: %v", tableMeshTopology, err)
|
2020-10-08 15:47:09 +00:00
|
|
|
}
|
2021-01-29 01:48:51 +00:00
|
|
|
if err := indexUpdateMaxTxn(tx, idx, tableMeshTopology); err != nil {
|
|
|
|
return fmt.Errorf("failed updating %s index: %v", tableMeshTopology, err)
|
2020-10-08 15:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-09-03 23:38:03 +00:00
|
|
|
func truncateGatewayServiceTopologyMappings(tx WriteTxn, idx uint64, gateway structs.ServiceName, kind string) error {
|
2020-10-08 15:47:09 +00:00
|
|
|
// Only ingress gateways are standalone items in the mesh topology viz
|
|
|
|
if kind != string(structs.ServiceKindIngressGateway) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-03-16 17:15:14 +00:00
|
|
|
if _, err := tx.DeleteAll(tableMeshTopology, indexDownstream, gateway); err != nil {
|
2021-01-29 01:48:51 +00:00
|
|
|
return fmt.Errorf("failed to truncate %s table: %v", tableMeshTopology, err)
|
2020-10-08 15:47:09 +00:00
|
|
|
}
|
2021-01-29 01:48:51 +00:00
|
|
|
if err := indexUpdateMaxTxn(tx, idx, tableMeshTopology); err != nil {
|
|
|
|
return fmt.Errorf("failed updating %s index: %v", tableMeshTopology, err)
|
2020-10-08 15:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2021-12-02 00:44:13 +00:00
|
|
|
|
|
|
|
func upsertKindServiceName(tx WriteTxn, idx uint64, kind structs.ServiceKind, name structs.ServiceName) error {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
// TODO(peering): make this peering aware
|
2021-12-02 00:44:13 +00:00
|
|
|
q := KindServiceNameQuery{Name: name.Name, Kind: kind, EnterpriseMeta: name.EnterpriseMeta}
|
|
|
|
existing, err := tx.First(tableKindServiceNames, indexID, q)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Service name is already known. Nothing to do.
|
|
|
|
if existing != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
ksn := KindServiceName{
|
|
|
|
Kind: kind,
|
|
|
|
Service: name,
|
|
|
|
RaftIndex: structs.RaftIndex{
|
|
|
|
CreateIndex: idx,
|
|
|
|
ModifyIndex: idx,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if err := tx.Insert(tableKindServiceNames, &ksn); err != nil {
|
|
|
|
return fmt.Errorf("failed inserting %s/%s into %s: %s", kind, name.String(), tableKindServiceNames, err)
|
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return updateKindServiceNamesIndex(tx, idx, kind, name.EnterpriseMeta)
|
2021-12-02 00:44:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func cleanupKindServiceName(tx WriteTxn, idx uint64, name structs.ServiceName, kind structs.ServiceKind) error {
|
|
|
|
q := KindServiceNameQuery{Name: name.Name, Kind: kind, EnterpriseMeta: name.EnterpriseMeta}
|
|
|
|
if _, err := tx.DeleteAll(tableKindServiceNames, indexID, q); err != nil {
|
|
|
|
return fmt.Errorf("failed to delete %s from %s: %s", name, tableKindServiceNames, err)
|
|
|
|
}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
return updateKindServiceNamesIndex(tx, idx, kind, name.EnterpriseMeta)
|
2021-12-02 00:44:13 +00:00
|
|
|
}
|
2022-03-22 23:58:41 +00:00
|
|
|
|
|
|
|
// CatalogDump returns all the contents of the node, service and check tables.
|
|
|
|
// In Enterprise, this will return entries across all partitions and namespaces.
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
// TODO(peering) make this peering aware?
|
2022-03-22 23:58:41 +00:00
|
|
|
func (s *Store) CatalogDump() (*structs.CatalogContents, error) {
|
|
|
|
tx := s.db.Txn(false)
|
|
|
|
contents := &structs.CatalogContents{}
|
|
|
|
|
|
|
|
nodes, err := tx.Get(tableNodes, indexID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed nodes lookup: %s", err)
|
|
|
|
}
|
|
|
|
for node := nodes.Next(); node != nil; node = nodes.Next() {
|
|
|
|
n := node.(*structs.Node)
|
|
|
|
contents.Nodes = append(contents.Nodes, n)
|
|
|
|
}
|
|
|
|
|
|
|
|
services, err := tx.Get(tableServices, indexID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed services lookup: %s", err)
|
|
|
|
}
|
|
|
|
for service := services.Next(); service != nil; service = services.Next() {
|
|
|
|
svc := service.(*structs.ServiceNode)
|
|
|
|
contents.Services = append(contents.Services, svc)
|
|
|
|
}
|
|
|
|
|
|
|
|
checks, err := tx.Get(tableChecks, indexID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed checks lookup: %s", err)
|
|
|
|
}
|
|
|
|
for check := checks.Next(); check != nil; check = checks.Next() {
|
|
|
|
c := check.(*structs.HealthCheck)
|
|
|
|
contents.Checks = append(contents.Checks, c)
|
|
|
|
}
|
|
|
|
|
|
|
|
return contents, nil
|
|
|
|
}
|