Cleanup state file during Unlock

Close and remove the file descriptor from LocalState if we Unlock the
state. Also remove an empty state file if we created it and it was never
written to. This is mostly to clean up after tests, but doesn't hurt to
not leave empty files around.
This commit is contained in:
James Bardin 2017-02-03 18:58:18 -05:00
parent cd96bb5aca
commit e92559f518
1 changed files with 35 additions and 16 deletions

View File

@ -39,6 +39,10 @@ type LocalState struct {
// the file handle corresponding to PathOut // the file handle corresponding to PathOut
stateFileOut *os.File stateFileOut *os.File
// created is set to tru if stateFileOut didn't exist before we created it.
// This is mostly so we can clean up emtpy files during tests, but doesn't
// hurt to remove file we never wrote to.
created bool
state *terraform.State state *terraform.State
readState *terraform.State readState *terraform.State
@ -75,8 +79,26 @@ func (s *LocalState) Lock(reason string) error {
} }
func (s *LocalState) Unlock() error { func (s *LocalState) Unlock() error {
// we can't be locked if we don't have a file
if s.stateFileOut == nil {
return nil
}
os.Remove(s.lockInfoPath()) os.Remove(s.lockInfoPath())
return s.unlock()
fileName := s.stateFileOut.Name()
unlockErr := s.unlock()
s.stateFileOut.Close()
s.stateFileOut = nil
// clean up the state file if we created it an never wrote to it
stat, err := os.Stat(fileName)
if err == nil && stat.Size() == 0 && s.created {
os.Remove(fileName)
}
return unlockErr
} }
// Open the state file, creating the directories and file as needed. // Open the state file, creating the directories and file as needed.
@ -85,28 +107,25 @@ func (s *LocalState) createStateFiles() error {
s.PathOut = s.Path s.PathOut = s.Path
} }
f, err := createFileAndDirs(s.PathOut) // yes this could race, but we only use it to clean up empty files
if _, err := os.Stat(s.PathOut); os.IsNotExist(err) {
s.created = true
}
// Create all the directories
if err := os.MkdirAll(filepath.Dir(s.PathOut), 0755); err != nil {
return err
}
f, err := os.OpenFile(s.PathOut, os.O_RDWR|os.O_CREATE, 0666)
if err != nil { if err != nil {
return err return err
} }
s.stateFileOut = f s.stateFileOut = f
return nil return nil
} }
func createFileAndDirs(path string) (*os.File, error) {
// Create all the directories
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
return nil, err
}
f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0666)
if err != nil {
return nil, err
}
return f, nil
}
// WriteState for LocalState always persists the state as well. // WriteState for LocalState always persists the state as well.
// TODO: this should use a more robust method of writing state, by first // TODO: this should use a more robust method of writing state, by first
// writing to a temp file on the same filesystem, and renaming the file over // writing to a temp file on the same filesystem, and renaming the file over