mirror of
https://github.com/rancher/os.git
synced 2025-09-11 03:31:04 +00:00
Atomic writes
This commit is contained in:
@@ -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))
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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) {
|
||||||
|
28
util/util.go
28
util/util.go
@@ -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 {
|
||||||
|
Reference in New Issue
Block a user