package mcnutils import ( "crypto/rand" "encoding/hex" "encoding/json" "fmt" "io" "os" "runtime" "strconv" "time" "github.com/docker/machine/libmachine/log" ) // GetHomeDir returns the home directory // TODO: Having this here just strikes me as dangerous, but some of the drivers // depend on it ;_; func GetHomeDir() string { if runtime.GOOS == "windows" { return os.Getenv("USERPROFILE") } return os.Getenv("HOME") } func GetUsername() string { u := "unknown" osUser := "" switch runtime.GOOS { case "darwin", "linux": osUser = os.Getenv("USER") case "windows": osUser = os.Getenv("USERNAME") } if osUser != "" { u = osUser } return u } func CopyFile(src, dst string) error { in, err := os.Open(src) if err != nil { return err } defer in.Close() out, err := os.Create(dst) if err != nil { return err } defer out.Close() if _, err = io.Copy(out, in); err != nil { return err } fi, err := os.Stat(src) if err != nil { return err } if err := os.Chmod(dst, fi.Mode()); err != nil { return err } return nil } func WaitForSpecificOrError(f func() (bool, error), maxAttempts int, waitInterval time.Duration) error { for i := 0; i < maxAttempts; i++ { stop, err := f() if err != nil { return err } if stop { return nil } time.Sleep(waitInterval) } return fmt.Errorf("Maximum number of retries (%d) exceeded", maxAttempts) } func WaitForSpecific(f func() bool, maxAttempts int, waitInterval time.Duration) error { return WaitForSpecificOrError(func() (bool, error) { return f(), nil }, maxAttempts, waitInterval) } func WaitFor(f func() bool) error { return WaitForSpecific(f, 60, 3*time.Second) } func DumpVal(vals ...interface{}) { for _, val := range vals { prettyJSON, err := json.MarshalIndent(val, "", " ") if err != nil { log.Warn(err) } log.Debug(string(prettyJSON)) } } // TruncateID returns a shorten id // Following two functions are from github.com/docker/docker/utils module. It // was way overkill to include the whole module, so we just have these bits // that we're using here. func TruncateID(id string) string { shortLen := 12 if len(id) < shortLen { shortLen = len(id) } return id[:shortLen] } // GenerateRandomID returns an unique id func GenerateRandomID() string { for { id := make([]byte, 32) if _, err := io.ReadFull(rand.Reader, id); err != nil { panic(err) // This shouldn't happen } value := hex.EncodeToString(id) // if we try to parse the truncated for as an int and we don't have // an error then the value is all numeric and causes issues when // used as a hostname. ref #3869 if _, err := strconv.ParseInt(TruncateID(value), 10, 64); err == nil { continue } return value } }