From c965809d44428048bc8d950852cdc30dbb456d07 Mon Sep 17 00:00:00 2001 From: Tim Gross Date: Thu, 21 Jul 2022 16:13:52 -0400 Subject: [PATCH] block deleting namespaces if the namespace contains a volume (#13880) When we delete a namespace, we check to ensure that there are no non-terminal jobs, which effectively covers evals, allocs, etc. CSI volumes are also namespaced, so extend this check to cover CSI volumes. --- .changelog/13880.txt | 3 +++ nomad/state/state_store.go | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 .changelog/13880.txt diff --git a/.changelog/13880.txt b/.changelog/13880.txt new file mode 100644 index 00000000000..31cdaca0fd7 --- /dev/null +++ b/.changelog/13880.txt @@ -0,0 +1,3 @@ +```release-note:bug +namespaces: Fixed a bug that allowed deleting a namespace that contained a CSI volume +``` diff --git a/nomad/state/state_store.go b/nomad/state/state_store.go index d62f6f032d6..d53f32e90af 100644 --- a/nomad/state/state_store.go +++ b/nomad/state/state_store.go @@ -2316,6 +2316,11 @@ func (s *StateStore) CSIVolumesByNodeID(ws memdb.WatchSet, prefix, nodeID string func (s *StateStore) CSIVolumesByNamespace(ws memdb.WatchSet, namespace, prefix string) (memdb.ResultIterator, error) { txn := s.db.ReadTxn() + return s.csiVolumesByNamespaceImpl(txn, ws, namespace, prefix) +} + +func (s *StateStore) csiVolumesByNamespaceImpl(txn *txn, ws memdb.WatchSet, namespace, prefix string) (memdb.ResultIterator, error) { + iter, err := txn.Get("csi_volumes", "id_prefix", namespace, prefix) if err != nil { return nil, fmt.Errorf("volume lookup failed: %v", err) @@ -5998,6 +6003,17 @@ func (s *StateStore) DeleteNamespaces(index uint64, names []string) error { } } + vIter, err := s.csiVolumesByNamespaceImpl(txn, nil, name, "") + if err != nil { + return err + } + rawVol := vIter.Next() + if rawVol != nil { + vol := rawVol.(*structs.CSIVolume) + return fmt.Errorf("namespace %q contains at least one CSI volume %q. "+ + "All CSI volumes in namespace must be deleted before it can be deleted", name, vol.ID) + } + // Delete the namespace if err := txn.Delete(TableNamespaces, existing); err != nil { return fmt.Errorf("namespace deletion failed: %v", err)