2013-05-14 22:37:35 +00:00
|
|
|
package utils
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
2013-11-07 20:19:24 +00:00
|
|
|
"runtime"
|
2013-05-14 22:37:35 +00:00
|
|
|
"strings"
|
2014-05-05 22:51:32 +00:00
|
|
|
|
2014-11-01 16:23:08 +00:00
|
|
|
"github.com/docker/docker/pkg/archive"
|
2015-04-01 14:21:07 +00:00
|
|
|
"github.com/docker/docker/pkg/stringid"
|
2013-05-14 22:37:35 +00:00
|
|
|
)
|
|
|
|
|
2013-11-14 06:08:08 +00:00
|
|
|
var globalTestID string
|
|
|
|
|
|
|
|
// TestDirectory creates a new temporary directory and returns its path.
|
|
|
|
// The contents of directory at path `templateDir` is copied into the
|
|
|
|
// new directory.
|
|
|
|
func TestDirectory(templateDir string) (dir string, err error) {
|
|
|
|
if globalTestID == "" {
|
2015-07-29 00:19:17 +00:00
|
|
|
globalTestID = stringid.GenerateNonCryptoID()[:4]
|
2013-11-14 06:08:08 +00:00
|
|
|
}
|
|
|
|
prefix := fmt.Sprintf("docker-test%s-%s-", globalTestID, GetCallerName(2))
|
|
|
|
if prefix == "" {
|
|
|
|
prefix = "docker-test-"
|
|
|
|
}
|
|
|
|
dir, err = ioutil.TempDir("", prefix)
|
|
|
|
if err = os.Remove(dir); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if templateDir != "" {
|
2014-11-01 16:23:08 +00:00
|
|
|
if err = archive.CopyWithTar(templateDir, dir); err != nil {
|
2013-11-14 06:08:08 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetCallerName introspects the call stack and returns the name of the
|
|
|
|
// function `depth` levels down in the stack.
|
|
|
|
func GetCallerName(depth int) string {
|
|
|
|
// Use the caller function name as a prefix.
|
|
|
|
// This helps trace temp directories back to their test.
|
|
|
|
pc, _, _, _ := runtime.Caller(depth + 1)
|
|
|
|
callerLongName := runtime.FuncForPC(pc).Name()
|
|
|
|
parts := strings.Split(callerLongName, ".")
|
|
|
|
callerShortName := parts[len(parts)-1]
|
|
|
|
return callerShortName
|
|
|
|
}
|
2013-11-25 22:42:22 +00:00
|
|
|
|
2015-07-21 21:20:12 +00:00
|
|
|
// ReplaceOrAppendEnvValues returns the defaults with the overrides either
|
2014-03-01 07:29:00 +00:00
|
|
|
// replaced by env key or appended to the list
|
|
|
|
func ReplaceOrAppendEnvValues(defaults, overrides []string) []string {
|
|
|
|
cache := make(map[string]int, len(defaults))
|
|
|
|
for i, e := range defaults {
|
|
|
|
parts := strings.SplitN(e, "=", 2)
|
|
|
|
cache[parts[0]] = i
|
|
|
|
}
|
2015-01-16 20:57:08 +00:00
|
|
|
|
2014-03-01 07:29:00 +00:00
|
|
|
for _, value := range overrides {
|
2015-01-16 20:57:08 +00:00
|
|
|
// Values w/o = means they want this env to be removed/unset.
|
|
|
|
if !strings.Contains(value, "=") {
|
|
|
|
if i, exists := cache[value]; exists {
|
|
|
|
defaults[i] = "" // Used to indicate it should be removed
|
|
|
|
}
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Just do a normal set/update
|
2014-03-01 07:29:00 +00:00
|
|
|
parts := strings.SplitN(value, "=", 2)
|
|
|
|
if i, exists := cache[parts[0]]; exists {
|
|
|
|
defaults[i] = value
|
|
|
|
} else {
|
|
|
|
defaults = append(defaults, value)
|
|
|
|
}
|
|
|
|
}
|
2015-01-16 20:57:08 +00:00
|
|
|
|
|
|
|
// Now remove all entries that we want to "unset"
|
|
|
|
for i := 0; i < len(defaults); i++ {
|
|
|
|
if defaults[i] == "" {
|
|
|
|
defaults = append(defaults[:i], defaults[i+1:]...)
|
|
|
|
i--
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-01 07:29:00 +00:00
|
|
|
return defaults
|
|
|
|
}
|