mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
command: Fix TestMetaBackend_localDoesNotDeleteLocal
The changes to how we handle setting the state path on the local backend broke the heuristic we were using here for detecting migration from one local backend to another with the same state path, which would by default end up deleting the state altogether after migration. We now use the StatePaths method to do this, which takes into account both the default values and any settings that have been set. Additionally this addresses a flaw in the old method which could potentially have deleted all non-default workspace state files if the "path" setting were changed without also changing the "workspace_dir" setting. This new approach is conservative because it will preserve all of the files if any one overlaps.
This commit is contained in:
parent
be79bf0412
commit
27abd9c6b8
@ -528,6 +528,42 @@ func (b *Local) StatePaths(name string) (stateIn, stateOut, backupOut string) {
|
||||
return statePath, stateOutPath, backupPath
|
||||
}
|
||||
|
||||
// PathsConflictWith returns true if any state path used by a workspace in
|
||||
// the receiver is the same as any state path used by the other given
|
||||
// local backend instance.
|
||||
//
|
||||
// This should be used when "migrating" from one local backend configuration to
|
||||
// another in order to avoid deleting the "old" state snapshots if they are
|
||||
// in the same files as the "new" state snapshots.
|
||||
func (b *Local) PathsConflictWith(other *Local) bool {
|
||||
otherPaths := map[string]struct{}{}
|
||||
otherWorkspaces, err := other.Workspaces()
|
||||
if err != nil {
|
||||
// If we can't enumerate the workspaces then we'll conservatively
|
||||
// assume that paths _do_ overlap, since we can't be certain.
|
||||
return true
|
||||
}
|
||||
for _, name := range otherWorkspaces {
|
||||
p, _, _ := other.StatePaths(name)
|
||||
otherPaths[p] = struct{}{}
|
||||
}
|
||||
|
||||
ourWorkspaces, err := other.Workspaces()
|
||||
if err != nil {
|
||||
// If we can't enumerate the workspaces then we'll conservatively
|
||||
// assume that paths _do_ overlap, since we can't be certain.
|
||||
return true
|
||||
}
|
||||
|
||||
for _, name := range ourWorkspaces {
|
||||
p, _, _ := b.StatePaths(name)
|
||||
if _, exists := otherPaths[p]; exists {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// this only ensures that the named directory exists
|
||||
func (b *Local) createState(name string) error {
|
||||
if name == backend.DefaultStateName {
|
||||
|
@ -668,13 +668,15 @@ func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *state.LocalSta
|
||||
erase := true
|
||||
if newLocalB, ok := b.(*backendLocal.Local); ok {
|
||||
if localB, ok := localB.(*backendLocal.Local); ok {
|
||||
if newLocalB.StatePath == localB.StatePath {
|
||||
if newLocalB.PathsConflictWith(localB) {
|
||||
erase = false
|
||||
log.Printf("[TRACE] Meta.Backend: both old and new backends share the same local state paths, so not erasing old state")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if erase {
|
||||
log.Printf("[TRACE] Meta.Backend: removing old state snapshots from old backend")
|
||||
for _, localState := range localStates {
|
||||
// We always delete the local state, unless that was our new state too.
|
||||
if err := localState.WriteState(nil); err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user