2badb01d30
The Catalog, Config Entry, KV and Session resources potentially re-validate the input as its coming in. We need to prevent snapshot restoration failures due to missing namespaces or namespaces that are being deleted in enterprise.
333 lines
9.3 KiB
Go
333 lines
9.3 KiB
Go
// +build !consulent
|
|
|
|
package state
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/consul/agent/structs"
|
|
memdb "github.com/hashicorp/go-memdb"
|
|
)
|
|
|
|
// servicesTableSchema returns a new table schema used to store information
|
|
// about services.
|
|
func servicesTableSchema() *memdb.TableSchema {
|
|
return &memdb.TableSchema{
|
|
Name: "services",
|
|
Indexes: map[string]*memdb.IndexSchema{
|
|
"id": {
|
|
Name: "id",
|
|
AllowMissing: false,
|
|
Unique: true,
|
|
Indexer: &memdb.CompoundIndex{
|
|
Indexes: []memdb.Indexer{
|
|
&memdb.StringFieldIndex{
|
|
Field: "Node",
|
|
Lowercase: true,
|
|
},
|
|
&memdb.StringFieldIndex{
|
|
Field: "ServiceID",
|
|
Lowercase: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"node": {
|
|
Name: "node",
|
|
AllowMissing: false,
|
|
Unique: false,
|
|
Indexer: &memdb.StringFieldIndex{
|
|
Field: "Node",
|
|
Lowercase: true,
|
|
},
|
|
},
|
|
"service": {
|
|
Name: "service",
|
|
AllowMissing: true,
|
|
Unique: false,
|
|
Indexer: &memdb.StringFieldIndex{
|
|
Field: "ServiceName",
|
|
Lowercase: true,
|
|
},
|
|
},
|
|
"connect": {
|
|
Name: "connect",
|
|
AllowMissing: true,
|
|
Unique: false,
|
|
Indexer: &IndexConnectService{},
|
|
},
|
|
"kind": {
|
|
Name: "kind",
|
|
AllowMissing: false,
|
|
Unique: false,
|
|
Indexer: &IndexServiceKind{},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// checksTableSchema returns a new table schema used for storing and indexing
|
|
// health check information. Health checks have a number of different attributes
|
|
// we want to filter by, so this table is a bit more complex.
|
|
func checksTableSchema() *memdb.TableSchema {
|
|
return &memdb.TableSchema{
|
|
Name: "checks",
|
|
Indexes: map[string]*memdb.IndexSchema{
|
|
"id": {
|
|
Name: "id",
|
|
AllowMissing: false,
|
|
Unique: true,
|
|
Indexer: &memdb.CompoundIndex{
|
|
Indexes: []memdb.Indexer{
|
|
&memdb.StringFieldIndex{
|
|
Field: "Node",
|
|
Lowercase: true,
|
|
},
|
|
&memdb.StringFieldIndex{
|
|
Field: "CheckID",
|
|
Lowercase: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"status": {
|
|
Name: "status",
|
|
AllowMissing: false,
|
|
Unique: false,
|
|
Indexer: &memdb.StringFieldIndex{
|
|
Field: "Status",
|
|
Lowercase: false,
|
|
},
|
|
},
|
|
"service": {
|
|
Name: "service",
|
|
AllowMissing: true,
|
|
Unique: false,
|
|
Indexer: &memdb.StringFieldIndex{
|
|
Field: "ServiceName",
|
|
Lowercase: true,
|
|
},
|
|
},
|
|
"node": {
|
|
Name: "node",
|
|
AllowMissing: true,
|
|
Unique: false,
|
|
Indexer: &memdb.StringFieldIndex{
|
|
Field: "Node",
|
|
Lowercase: true,
|
|
},
|
|
},
|
|
"node_service_check": {
|
|
Name: "node_service_check",
|
|
AllowMissing: true,
|
|
Unique: false,
|
|
Indexer: &memdb.CompoundIndex{
|
|
Indexes: []memdb.Indexer{
|
|
&memdb.StringFieldIndex{
|
|
Field: "Node",
|
|
Lowercase: true,
|
|
},
|
|
&memdb.FieldSetIndex{
|
|
Field: "ServiceID",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"node_service": {
|
|
Name: "node_service",
|
|
AllowMissing: true,
|
|
Unique: false,
|
|
Indexer: &memdb.CompoundIndex{
|
|
Indexes: []memdb.Indexer{
|
|
&memdb.StringFieldIndex{
|
|
Field: "Node",
|
|
Lowercase: true,
|
|
},
|
|
&memdb.StringFieldIndex{
|
|
Field: "ServiceID",
|
|
Lowercase: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func serviceIndexName(name string, _ *structs.EnterpriseMeta) string {
|
|
return fmt.Sprintf("service.%s", name)
|
|
}
|
|
|
|
func serviceKindIndexName(kind structs.ServiceKind, _ *structs.EnterpriseMeta) string {
|
|
switch kind {
|
|
case structs.ServiceKindTypical:
|
|
// needs a special case here
|
|
return "service_kind.typical"
|
|
default:
|
|
return "service_kind." + string(kind)
|
|
}
|
|
}
|
|
|
|
func catalogUpdateServicesIndexes(tx WriteTxn, idx uint64, _ *structs.EnterpriseMeta) error {
|
|
// overall services index
|
|
if err := indexUpdateMaxTxn(tx, idx, "services"); err != nil {
|
|
return fmt.Errorf("failed updating index: %s", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func catalogUpdateServiceKindIndexes(tx WriteTxn, kind structs.ServiceKind, idx uint64, _ *structs.EnterpriseMeta) error {
|
|
// service-kind index
|
|
if err := indexUpdateMaxTxn(tx, idx, serviceKindIndexName(kind, nil)); err != nil {
|
|
return fmt.Errorf("failed updating index: %s", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func catalogUpdateServiceIndexes(tx WriteTxn, serviceName string, idx uint64, _ *structs.EnterpriseMeta) error {
|
|
// per-service index
|
|
if err := indexUpdateMaxTxn(tx, idx, serviceIndexName(serviceName, nil)); err != nil {
|
|
return fmt.Errorf("failed updating index: %s", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func catalogUpdateServiceExtinctionIndex(tx WriteTxn, idx uint64, _ *structs.EnterpriseMeta) error {
|
|
if err := tx.Insert("index", &IndexEntry{serviceLastExtinctionIndexName, idx}); err != nil {
|
|
return fmt.Errorf("failed updating missing service extinction index: %s", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func catalogInsertService(tx WriteTxn, svc *structs.ServiceNode) error {
|
|
// Insert the service and update the index
|
|
if err := tx.Insert("services", svc); err != nil {
|
|
return fmt.Errorf("failed inserting service: %s", err)
|
|
}
|
|
|
|
if err := catalogUpdateServicesIndexes(tx, svc.ModifyIndex, &svc.EnterpriseMeta); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := catalogUpdateServiceIndexes(tx, svc.ServiceName, svc.ModifyIndex, &svc.EnterpriseMeta); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := catalogUpdateServiceKindIndexes(tx, svc.ServiceKind, svc.ModifyIndex, &svc.EnterpriseMeta); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func catalogServicesMaxIndex(tx ReadTxn, _ *structs.EnterpriseMeta) uint64 {
|
|
return maxIndexTxn(tx, "services")
|
|
}
|
|
|
|
func catalogServiceMaxIndex(tx ReadTxn, serviceName string, _ *structs.EnterpriseMeta) (<-chan struct{}, interface{}, error) {
|
|
return tx.FirstWatch("index", "id", serviceIndexName(serviceName, nil))
|
|
}
|
|
|
|
func catalogServiceKindMaxIndex(tx ReadTxn, ws memdb.WatchSet, kind structs.ServiceKind, entMeta *structs.EnterpriseMeta) uint64 {
|
|
return maxIndexWatchTxn(tx, ws, serviceKindIndexName(kind, nil))
|
|
}
|
|
|
|
func catalogServiceList(tx ReadTxn, _ *structs.EnterpriseMeta, _ bool) (memdb.ResultIterator, error) {
|
|
return tx.Get("services", "id")
|
|
}
|
|
|
|
func catalogServiceListByKind(tx ReadTxn, kind structs.ServiceKind, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
|
return tx.Get("services", "kind", string(kind))
|
|
}
|
|
|
|
func catalogServiceListByNode(tx ReadTxn, node string, _ *structs.EnterpriseMeta, _ bool) (memdb.ResultIterator, error) {
|
|
return tx.Get("services", "node", node)
|
|
}
|
|
|
|
func catalogServiceNodeList(tx ReadTxn, name string, index string, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
|
return tx.Get("services", index, name)
|
|
}
|
|
|
|
func catalogServiceLastExtinctionIndex(tx ReadTxn, _ *structs.EnterpriseMeta) (interface{}, error) {
|
|
return tx.First("index", "id", serviceLastExtinctionIndexName)
|
|
}
|
|
|
|
func catalogMaxIndex(tx ReadTxn, _ *structs.EnterpriseMeta, checks bool) uint64 {
|
|
if checks {
|
|
return maxIndexTxn(tx, "nodes", "services", "checks")
|
|
}
|
|
return maxIndexTxn(tx, "nodes", "services")
|
|
}
|
|
|
|
func catalogMaxIndexWatch(tx ReadTxn, ws memdb.WatchSet, _ *structs.EnterpriseMeta, checks bool) uint64 {
|
|
if checks {
|
|
return maxIndexWatchTxn(tx, ws, "nodes", "services", "checks")
|
|
}
|
|
return maxIndexWatchTxn(tx, ws, "nodes", "services")
|
|
}
|
|
|
|
func catalogUpdateCheckIndexes(tx WriteTxn, idx uint64, _ *structs.EnterpriseMeta) error {
|
|
// update the universal index entry
|
|
if err := tx.Insert("index", &IndexEntry{"checks", idx}); err != nil {
|
|
return fmt.Errorf("failed updating index: %s", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func catalogChecksMaxIndex(tx ReadTxn, _ *structs.EnterpriseMeta) uint64 {
|
|
return maxIndexTxn(tx, "checks")
|
|
}
|
|
|
|
func catalogListChecksByNode(tx ReadTxn, node string, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
|
return tx.Get("checks", "node", node)
|
|
}
|
|
|
|
func catalogListChecksByService(tx ReadTxn, service string, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
|
return tx.Get("checks", "service", service)
|
|
}
|
|
|
|
func catalogListChecksInState(tx ReadTxn, state string, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
|
// simpler than normal due to the use of the CompoundMultiIndex
|
|
return tx.Get("checks", "status", state)
|
|
}
|
|
|
|
func catalogListChecks(tx ReadTxn, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
|
return tx.Get("checks", "id")
|
|
}
|
|
|
|
func catalogListNodeChecks(tx ReadTxn, node string) (memdb.ResultIterator, error) {
|
|
return tx.Get("checks", "node_service_check", node, false)
|
|
}
|
|
|
|
func catalogListServiceChecks(tx ReadTxn, node string, service string, _ *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
|
return tx.Get("checks", "node_service", node, service)
|
|
}
|
|
|
|
func catalogInsertCheck(tx WriteTxn, chk *structs.HealthCheck, idx uint64) error {
|
|
// Insert the check
|
|
if err := tx.Insert("checks", chk); err != nil {
|
|
return fmt.Errorf("failed inserting check: %s", err)
|
|
}
|
|
|
|
if err := catalogUpdateCheckIndexes(tx, idx, &chk.EnterpriseMeta); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func catalogChecksForNodeService(tx ReadTxn, node string, service string, entMeta *structs.EnterpriseMeta) (memdb.ResultIterator, error) {
|
|
return tx.Get("checks", "node_service", node, service)
|
|
}
|
|
|
|
func validateRegisterRequestTxn(_ ReadTxn, _ *structs.RegisterRequest, _ bool) (*structs.EnterpriseMeta, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (s *Store) ValidateRegisterRequest(_ *structs.RegisterRequest) (*structs.EnterpriseMeta, error) {
|
|
return nil, nil
|
|
}
|