utils.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package utils
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "runtime"
  7. "strings"
  8. "github.com/docker/docker/pkg/archive"
  9. "github.com/docker/docker/pkg/stringid"
  10. )
  11. var globalTestID string
  12. // TestDirectory creates a new temporary directory and returns its path.
  13. // The contents of directory at path `templateDir` is copied into the
  14. // new directory.
  15. func TestDirectory(templateDir string) (dir string, err error) {
  16. if globalTestID == "" {
  17. globalTestID = stringid.GenerateNonCryptoID()[:4]
  18. }
  19. prefix := fmt.Sprintf("docker-test%s-%s-", globalTestID, GetCallerName(2))
  20. if prefix == "" {
  21. prefix = "docker-test-"
  22. }
  23. dir, err = ioutil.TempDir("", prefix)
  24. if err = os.Remove(dir); err != nil {
  25. return
  26. }
  27. if templateDir != "" {
  28. if err = archive.CopyWithTar(templateDir, dir); err != nil {
  29. return
  30. }
  31. }
  32. return
  33. }
  34. // GetCallerName introspects the call stack and returns the name of the
  35. // function `depth` levels down in the stack.
  36. func GetCallerName(depth int) string {
  37. // Use the caller function name as a prefix.
  38. // This helps trace temp directories back to their test.
  39. pc, _, _, _ := runtime.Caller(depth + 1)
  40. callerLongName := runtime.FuncForPC(pc).Name()
  41. parts := strings.Split(callerLongName, ".")
  42. callerShortName := parts[len(parts)-1]
  43. return callerShortName
  44. }
  45. // ReplaceOrAppendEnvValues returns the defaults with the overrides either
  46. // replaced by env key or appended to the list
  47. func ReplaceOrAppendEnvValues(defaults, overrides []string) []string {
  48. cache := make(map[string]int, len(defaults))
  49. for i, e := range defaults {
  50. parts := strings.SplitN(e, "=", 2)
  51. cache[parts[0]] = i
  52. }
  53. for _, value := range overrides {
  54. // Values w/o = means they want this env to be removed/unset.
  55. if !strings.Contains(value, "=") {
  56. if i, exists := cache[value]; exists {
  57. defaults[i] = "" // Used to indicate it should be removed
  58. }
  59. continue
  60. }
  61. // Just do a normal set/update
  62. parts := strings.SplitN(value, "=", 2)
  63. if i, exists := cache[parts[0]]; exists {
  64. defaults[i] = value
  65. } else {
  66. defaults = append(defaults, value)
  67. }
  68. }
  69. // Now remove all entries that we want to "unset"
  70. for i := 0; i < len(defaults); i++ {
  71. if defaults[i] == "" {
  72. defaults = append(defaults[:i], defaults[i+1:]...)
  73. i--
  74. }
  75. }
  76. return defaults
  77. }