From e92559f5182b199a2cf26b5fdbf4c528eb3fa243 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 3 Feb 2017 18:58:18 -0500 Subject: [PATCH] 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. --- state/local.go | 51 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/state/local.go b/state/local.go index e1129ebbe0..b34d048376 100644 --- a/state/local.go +++ b/state/local.go @@ -39,6 +39,10 @@ type LocalState struct { // the file handle corresponding to PathOut 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 readState *terraform.State @@ -75,8 +79,26 @@ func (s *LocalState) Lock(reason string) 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()) - 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. @@ -85,28 +107,25 @@ func (s *LocalState) createStateFiles() error { 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 { return err } + s.stateFileOut = f 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. // 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