From 0c2eea2918484538dd911c58c89374e53ab9d9dc Mon Sep 17 00:00:00 2001 From: Matt Keeler Date: Wed, 11 Nov 2020 15:12:10 -0500 Subject: [PATCH] Backport #9156 to 1.8.x (#9164) 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. --- .changelog/9156.txt | 3 +++ .changelog/_666.txt | 3 +++ agent/consul/state/catalog.go | 11 ++++------- agent/consul/state/catalog_oss.go | 2 +- agent/consul/state/kvs.go | 4 ++-- agent/consul/state/kvs_oss.go | 2 +- agent/consul/state/session.go | 4 ++-- agent/consul/state/session_oss.go | 2 +- 8 files changed, 17 insertions(+), 14 deletions(-) create mode 100644 .changelog/9156.txt create mode 100644 .changelog/_666.txt diff --git a/.changelog/9156.txt b/.changelog/9156.txt new file mode 100644 index 0000000000..c2867838a7 --- /dev/null +++ b/.changelog/9156.txt @@ -0,0 +1,3 @@ +```release-note:bug +namespace: **(Enterprise Only)** Fixed a bug that could case snapshot restoration to fail when it contained a namespace marked for deletion while still containing other resources in that namespace. +``` diff --git a/.changelog/_666.txt b/.changelog/_666.txt new file mode 100644 index 0000000000..226974992d --- /dev/null +++ b/.changelog/_666.txt @@ -0,0 +1,3 @@ +```release-note:bug +namespace: **(Enterprise Only)** Fixed an issue where namespaced services and checks were not being deleted when the containing namespace was deleted. +``` diff --git a/agent/consul/state/catalog.go b/agent/consul/state/catalog.go index 18edd648b3..2b4e58ff30 100644 --- a/agent/consul/state/catalog.go +++ b/agent/consul/state/catalog.go @@ -216,10 +216,7 @@ func (s *Snapshot) Checks(node string) (memdb.ResultIterator, error) { // performed within a single transaction to avoid race conditions on state // updates. func (s *Restore) Registration(idx uint64, req *structs.RegisterRequest) error { - if err := s.store.ensureRegistrationTxn(s.tx, idx, true, req); err != nil { - return err - } - return nil + return s.store.ensureRegistrationTxn(s.tx, idx, true, req, true) } // EnsureRegistration is used to make sure a node, service, and check @@ -229,7 +226,7 @@ func (s *Store) EnsureRegistration(idx uint64, req *structs.RegisterRequest) err tx := s.db.Txn(true) defer tx.Abort() - if err := s.ensureRegistrationTxn(tx, idx, false, req); err != nil { + if err := s.ensureRegistrationTxn(tx, idx, false, req, false); err != nil { return err } @@ -251,8 +248,8 @@ func (s *Store) ensureCheckIfNodeMatches(tx *memdb.Txn, idx uint64, preserveInde // 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. -func (s *Store) ensureRegistrationTxn(tx *memdb.Txn, idx uint64, preserveIndexes bool, req *structs.RegisterRequest) error { - if _, err := s.validateRegisterRequestTxn(tx, req); err != nil { +func (s *Store) ensureRegistrationTxn(tx *memdb.Txn, idx uint64, preserveIndexes bool, req *structs.RegisterRequest, restore bool) error { + if _, err := s.validateRegisterRequestTxn(tx, req, restore); err != nil { return err } diff --git a/agent/consul/state/catalog_oss.go b/agent/consul/state/catalog_oss.go index b6f20db65d..d404e93eb2 100644 --- a/agent/consul/state/catalog_oss.go +++ b/agent/consul/state/catalog_oss.go @@ -322,7 +322,7 @@ func (s *Store) catalogChecksForNodeService(tx *memdb.Txn, node string, service return tx.Get("checks", "node_service", node, service) } -func (s *Store) validateRegisterRequestTxn(tx *memdb.Txn, args *structs.RegisterRequest) (*structs.EnterpriseMeta, error) { +func (s *Store) validateRegisterRequestTxn(tx *memdb.Txn, args *structs.RegisterRequest, _ bool) (*structs.EnterpriseMeta, error) { return nil, nil } diff --git a/agent/consul/state/kvs.go b/agent/consul/state/kvs.go index ab412c133b..ef7d1fe7dd 100644 --- a/agent/consul/state/kvs.go +++ b/agent/consul/state/kvs.go @@ -69,7 +69,7 @@ func (s *Snapshot) Tombstones() (memdb.ResultIterator, error) { // KVS is used when restoring from a snapshot. Use KVSSet for general inserts. func (s *Restore) KVS(entry *structs.DirEntry) error { - if err := s.store.insertKVTxn(s.tx, entry, true); err != nil { + if err := s.store.insertKVTxn(s.tx, entry, true, true); err != nil { return fmt.Errorf("failed inserting kvs entry: %s", err) } @@ -155,7 +155,7 @@ func (s *Store) kvsSetTxn(tx *memdb.Txn, idx uint64, entry *structs.DirEntry, up entry.ModifyIndex = idx // Store the kv pair in the state store and update the index. - if err := s.insertKVTxn(tx, entry, false); err != nil { + if err := s.insertKVTxn(tx, entry, false, false); err != nil { return fmt.Errorf("failed inserting kvs entry: %s", err) } diff --git a/agent/consul/state/kvs_oss.go b/agent/consul/state/kvs_oss.go index 76dcb2ab56..df1a0590b8 100644 --- a/agent/consul/state/kvs_oss.go +++ b/agent/consul/state/kvs_oss.go @@ -16,7 +16,7 @@ func kvsIndexer() *memdb.StringFieldIndex { } } -func (s *Store) insertKVTxn(tx *memdb.Txn, entry *structs.DirEntry, updateMax bool) error { +func (s *Store) insertKVTxn(tx *memdb.Txn, entry *structs.DirEntry, updateMax bool, _ bool) error { if err := tx.Insert("kvs", entry); err != nil { return err } diff --git a/agent/consul/state/session.go b/agent/consul/state/session.go index 8f32bd3944..1256d2121d 100644 --- a/agent/consul/state/session.go +++ b/agent/consul/state/session.go @@ -146,7 +146,7 @@ func (s *Snapshot) Sessions() (memdb.ResultIterator, error) { // Session is used when restoring from a snapshot. For general inserts, use // SessionCreate. func (s *Restore) Session(sess *structs.Session) error { - if err := s.store.insertSessionTxn(s.tx, sess, sess.ModifyIndex, true); err != nil { + if err := s.store.insertSessionTxn(s.tx, sess, sess.ModifyIndex, true, true); err != nil { return fmt.Errorf("failed inserting session: %s", err) } @@ -214,7 +214,7 @@ func (s *Store) sessionCreateTxn(tx *memdb.Txn, idx uint64, sess *structs.Sessio } // Insert the session - if err := s.insertSessionTxn(tx, sess, idx, false); err != nil { + if err := s.insertSessionTxn(tx, sess, idx, false, false); err != nil { return fmt.Errorf("failed inserting session: %s", err) } diff --git a/agent/consul/state/session_oss.go b/agent/consul/state/session_oss.go index 1208f4d82b..4b23c058b4 100644 --- a/agent/consul/state/session_oss.go +++ b/agent/consul/state/session_oss.go @@ -48,7 +48,7 @@ func (s *Store) sessionDeleteWithSession(tx *memdb.Txn, session *structs.Session return nil } -func (s *Store) insertSessionTxn(tx *memdb.Txn, session *structs.Session, idx uint64, updateMax bool) error { +func (s *Store) insertSessionTxn(tx *memdb.Txn, session *structs.Session, idx uint64, updateMax bool, _ bool) error { if err := tx.Insert("sessions", session); err != nil { return err }