1
0
mirror of https://github.com/rancher/os.git synced 2025-09-11 03:31:04 +00:00

Atomic writes

This commit is contained in:
Josh Curl
2016-06-02 14:32:26 -07:00
parent 97344cc535
commit 4f48569cb2
6 changed files with 34 additions and 20 deletions

View File

@@ -18,7 +18,6 @@ package cloudinit
import ( import (
"errors" "errors"
"flag" "flag"
"io/ioutil"
"os" "os"
"strings" "strings"
"sync" "sync"
@@ -40,6 +39,7 @@ import (
"github.com/coreos/coreos-cloudinit/system" "github.com/coreos/coreos-cloudinit/system"
"github.com/rancher/netconf" "github.com/rancher/netconf"
rancherConfig "github.com/rancher/os/config" rancherConfig "github.com/rancher/os/config"
"github.com/rancher/os/util"
) )
const ( const (
@@ -71,13 +71,13 @@ func saveFiles(cloudConfigBytes, scriptBytes []byte, metadata datasource.Metadat
if len(scriptBytes) > 0 { if len(scriptBytes) > 0 {
log.Infof("Writing to %s", rancherConfig.CloudConfigScriptFile) log.Infof("Writing to %s", rancherConfig.CloudConfigScriptFile)
if err := ioutil.WriteFile(rancherConfig.CloudConfigScriptFile, scriptBytes, 500); err != nil { if err := util.WriteFileAtomic(rancherConfig.CloudConfigScriptFile, scriptBytes, 500); err != nil {
log.Errorf("Error while writing file %s: %v", rancherConfig.CloudConfigScriptFile, err) log.Errorf("Error while writing file %s: %v", rancherConfig.CloudConfigScriptFile, err)
return err return err
} }
} }
if err := ioutil.WriteFile(rancherConfig.CloudConfigBootFile, cloudConfigBytes, 400); err != nil { if err := util.WriteFileAtomic(rancherConfig.CloudConfigBootFile, cloudConfigBytes, 400); err != nil {
return err return err
} }
log.Infof("Written to %s:\n%s", rancherConfig.CloudConfigBootFile, string(cloudConfigBytes)) log.Infof("Written to %s:\n%s", rancherConfig.CloudConfigBootFile, string(cloudConfigBytes))
@@ -87,7 +87,7 @@ func saveFiles(cloudConfigBytes, scriptBytes []byte, metadata datasource.Metadat
return err return err
} }
if err = ioutil.WriteFile(rancherConfig.MetaDataFile, metaDataBytes, 400); err != nil { if err = util.WriteFileAtomic(rancherConfig.MetaDataFile, metaDataBytes, 400); err != nil {
return err return err
} }
log.Infof("Written to %s:\n%s", rancherConfig.MetaDataFile, string(metaDataBytes)) log.Infof("Written to %s:\n%s", rancherConfig.MetaDataFile, string(metaDataBytes))

View File

@@ -1,11 +1,11 @@
package cloudinit package cloudinit
import ( import (
"io/ioutil"
"strings" "strings"
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
yaml "github.com/cloudfoundry-incubator/candiedyaml" yaml "github.com/cloudfoundry-incubator/candiedyaml"
"github.com/rancher/os/util"
"google.golang.org/cloud/compute/metadata" "google.golang.org/cloud/compute/metadata"
) )
@@ -111,7 +111,7 @@ func (cc *GceCloudConfig) getMergedUserData() ([]byte, error) {
} }
func writeFile(filename string, data []byte) error { func writeFile(filename string, data []byte) error {
if err := ioutil.WriteFile(filename, data, 400); err != nil { if err := util.WriteFileAtomic(filename, data, 400); err != nil {
log.Errorf("Could not write file %v", err) log.Errorf("Could not write file %v", err)
return err return err
} }

View File

@@ -14,6 +14,7 @@ import (
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
"github.com/rancher/os/config" "github.com/rancher/os/config"
"github.com/rancher/os/util"
) )
func configSubcommands() []cli.Command { func configSubcommands() []cli.Command {
@@ -202,7 +203,7 @@ func export(c *cli.Context) error {
if output == "" { if output == "" {
fmt.Println(content) fmt.Println(content)
} else { } else {
err := ioutil.WriteFile(output, []byte(content), 0400) err := util.WriteFileAtomic(output, []byte(content), 0400)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@@ -10,6 +10,7 @@ import (
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
machineUtil "github.com/docker/machine/utils" machineUtil "github.com/docker/machine/utils"
"github.com/rancher/os/config" "github.com/rancher/os/config"
"github.com/rancher/os/util"
) )
const ( const (
@@ -79,11 +80,11 @@ func writeCerts(generateServer bool, hostname []string, cfg *config.CloudConfig,
return err return err
} }
if err := ioutil.WriteFile(certPath, []byte(cfg.Rancher.Docker.ServerCert), 0400); err != nil { if err := util.WriteFileAtomic(certPath, []byte(cfg.Rancher.Docker.ServerCert), 0400); err != nil {
return err return err
} }
return ioutil.WriteFile(keyPath, []byte(cfg.Rancher.Docker.ServerKey), 0400) return util.WriteFileAtomic(keyPath, []byte(cfg.Rancher.Docker.ServerKey), 0400)
} }
@@ -117,11 +118,11 @@ func writeCaCerts(cfg *config.CloudConfig, caCertPath, caKeyPath string) error {
return err return err
} }
if err := ioutil.WriteFile(caCertPath, []byte(cfg.Rancher.Docker.CACert), 0400); err != nil { if err := util.WriteFileAtomic(caCertPath, []byte(cfg.Rancher.Docker.CACert), 0400); err != nil {
return err return err
} }
if err := ioutil.WriteFile(caKeyPath, []byte(cfg.Rancher.Docker.CAKey), 0400); err != nil { if err := util.WriteFileAtomic(caKeyPath, []byte(cfg.Rancher.Docker.CAKey), 0400); err != nil {
return err return err
} }

View File

@@ -239,7 +239,7 @@ func WriteToFile(data interface{}, filename string) error {
return err return err
} }
return ioutil.WriteFile(filename, content, 400) return util.WriteFileAtomic(filename, content, 400)
} }
func readConfig(bytes []byte, substituteMetadataVars bool, files ...string) (map[interface{}]interface{}, error) { func readConfig(bytes []byte, substituteMetadataVars bool, files ...string) (map[interface{}]interface{}, error) {

View File

@@ -2,8 +2,10 @@ package util
import ( import (
"bytes" "bytes"
"io" "fmt"
"io/ioutil"
"os" "os"
"path"
"strings" "strings"
yaml "github.com/cloudfoundry-incubator/candiedyaml" yaml "github.com/cloudfoundry-incubator/candiedyaml"
@@ -29,23 +31,33 @@ func Contains(values []string, value string) bool {
type ReturnsErr func() error type ReturnsErr func() error
func FileCopy(src, dest string) (err error) { func FileCopy(src, dest string) error {
in, err := os.Open(src) data, err := ioutil.ReadFile(src)
if err != nil { if err != nil {
return err return err
} }
defer func() { err = in.Close() }() return WriteFileAtomic(dest, data, 0666)
}
out, err := os.Create(dest) func WriteFileAtomic(filename string, data []byte, perm os.FileMode) error {
dir, file := path.Split(filename)
tempFile, err := ioutil.TempFile(dir, fmt.Sprintf(".%s", file))
if err != nil { if err != nil {
return err return err
} }
defer func() { err = out.Close() }() defer os.Remove(tempFile.Name())
if _, err := io.Copy(out, in); err != nil { if _, err := tempFile.Write(data); err != nil {
return err return err
} }
return if err := tempFile.Close(); err != nil {
return err
}
if err := os.Chmod(tempFile.Name(), perm); err != nil {
return err
}
return os.Rename(tempFile.Name(), filename)
} }
func Convert(from, to interface{}) error { func Convert(from, to interface{}) error {