utils.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. package utils
  2. import (
  3. "crypto/rand"
  4. "encoding/hex"
  5. "encoding/json"
  6. "fmt"
  7. "io"
  8. "net"
  9. "os"
  10. "path/filepath"
  11. "runtime"
  12. "strconv"
  13. "time"
  14. "github.com/docker/machine/log"
  15. )
  16. func GetHomeDir() string {
  17. if runtime.GOOS == "windows" {
  18. return os.Getenv("USERPROFILE")
  19. }
  20. return os.Getenv("HOME")
  21. }
  22. func GetBaseDir() string {
  23. baseDir := os.Getenv("MACHINE_STORAGE_PATH")
  24. if baseDir == "" {
  25. baseDir = filepath.Join(GetHomeDir(), ".docker", "machine")
  26. }
  27. return baseDir
  28. }
  29. func GetDockerDir() string {
  30. return filepath.Join(GetHomeDir(), ".docker")
  31. }
  32. func GetMachineDir() string {
  33. return filepath.Join(GetBaseDir(), "machines")
  34. }
  35. func GetMachineCertDir() string {
  36. return filepath.Join(GetBaseDir(), "certs")
  37. }
  38. func GetMachineCacheDir() string {
  39. return filepath.Join(GetBaseDir(), "cache")
  40. }
  41. func GetUsername() string {
  42. u := "unknown"
  43. osUser := ""
  44. switch runtime.GOOS {
  45. case "darwin", "linux":
  46. osUser = os.Getenv("USER")
  47. case "windows":
  48. osUser = os.Getenv("USERNAME")
  49. }
  50. if osUser != "" {
  51. u = osUser
  52. }
  53. return u
  54. }
  55. func CopyFile(src, dst string) error {
  56. in, err := os.Open(src)
  57. if err != nil {
  58. return err
  59. }
  60. defer in.Close()
  61. out, err := os.Create(dst)
  62. if err != nil {
  63. return err
  64. }
  65. if _, err = io.Copy(out, in); err != nil {
  66. return err
  67. }
  68. fi, err := os.Stat(src)
  69. if err != nil {
  70. return err
  71. }
  72. if err := os.Chmod(dst, fi.Mode()); err != nil {
  73. return err
  74. }
  75. return nil
  76. }
  77. func WaitForSpecificOrError(f func() (bool, error), maxAttempts int, waitInterval time.Duration) error {
  78. for i := 0; i < maxAttempts; i++ {
  79. stop, err := f()
  80. if err != nil {
  81. return err
  82. }
  83. if stop {
  84. return nil
  85. }
  86. time.Sleep(waitInterval)
  87. }
  88. return fmt.Errorf("Maximum number of retries (%d) exceeded", maxAttempts)
  89. }
  90. func WaitForSpecific(f func() bool, maxAttempts int, waitInterval time.Duration) error {
  91. return WaitForSpecificOrError(func() (bool, error) {
  92. return f(), nil
  93. }, maxAttempts, waitInterval)
  94. }
  95. func WaitFor(f func() bool) error {
  96. return WaitForSpecific(f, 60, 3*time.Second)
  97. }
  98. func WaitForDocker(ip string, daemonPort int) error {
  99. return WaitFor(func() bool {
  100. conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", ip, daemonPort))
  101. if err != nil {
  102. log.Debugf("Daemon not responding yet: %s", err)
  103. return false
  104. }
  105. conn.Close()
  106. return true
  107. })
  108. }
  109. func DumpVal(vals ...interface{}) {
  110. for _, val := range vals {
  111. prettyJSON, err := json.MarshalIndent(val, "", " ")
  112. if err != nil {
  113. log.Fatal(err)
  114. }
  115. log.Debug(string(prettyJSON))
  116. }
  117. }
  118. // Following two functions are from github.com/docker/docker/utils module. It
  119. // was way overkill to include the whole module, so we just have these bits
  120. // that we're using here.
  121. func TruncateID(id string) string {
  122. shortLen := 12
  123. if len(id) < shortLen {
  124. shortLen = len(id)
  125. }
  126. return id[:shortLen]
  127. }
  128. // GenerateRandomID returns an unique id
  129. func GenerateRandomID() string {
  130. for {
  131. id := make([]byte, 32)
  132. if _, err := io.ReadFull(rand.Reader, id); err != nil {
  133. panic(err) // This shouldn't happen
  134. }
  135. value := hex.EncodeToString(id)
  136. // if we try to parse the truncated for as an int and we don't have
  137. // an error then the value is all numberic and causes issues when
  138. // used as a hostname. ref #3869
  139. if _, err := strconv.ParseInt(TruncateID(value), 10, 64); err == nil {
  140. continue
  141. }
  142. return value
  143. }
  144. }