Now this change ensures `config.json` is first written into a temp-file and
rename into the original file, if no errors from the FS. If ENOSPC occurs on write,
when the machine is restarted, the previous `config.json` is still available on startup.

Extended `TestStoreSave()` to check for any residual config files in the
machine directory.

Signed-off-by: Anil Belur <askb23@gmail.com>
This commit is contained in:
Anil Belur 2015-11-29 09:08:03 +05:30
parent df20cc4713
commit 1a3c3898c1
2 changed files with 37 additions and 1 deletions

View File

@ -31,7 +31,31 @@ func (s Filestore) GetMachinesDir() string {
}
func (s Filestore) saveToFile(data []byte, file string) error {
if _, err := os.Stat(file); os.IsNotExist(err) {
return ioutil.WriteFile(file, data, 0600)
}
tmpfi, err := ioutil.TempFile(filepath.Dir(file), "config.json.tmp")
if err != nil {
return err
}
defer os.Remove(tmpfi.Name())
err = ioutil.WriteFile(tmpfi.Name(), data, 0600)
if err != nil {
return err
}
err = os.Remove(file)
if err != nil {
return err
}
err = os.Rename(tmpfi.Name(), file)
if err != nil {
return err
}
return nil
}
func (s Filestore) Save(host *host.Host) error {

View File

@ -6,6 +6,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"regexp"
"testing"
"github.com/docker/machine/commands/mcndirs"
@ -52,6 +53,17 @@ func TestStoreSave(t *testing.T) {
if _, err := os.Stat(path); os.IsNotExist(err) {
t.Fatalf("Host path doesn't exist: %s", path)
}
files, _ := ioutil.ReadDir(path)
for _, f := range files {
r, err := regexp.Compile("config.json.tmp*")
if err != nil {
t.Fatalf("Failed to compile regexp string")
}
if r.MatchString(f.Name()) {
t.Fatalf("Failed to remove temp filestore:%s", f.Name())
}
}
}
func TestStoreSaveOmitRawDriver(t *testing.T) {