2013-05-14 18:37:35 -04:00
|
|
|
package utils
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
2013-11-07 15:19:24 -05:00
|
|
|
"runtime"
|
2013-05-14 18:37:35 -04:00
|
|
|
"strings"
|
2014-05-05 18:51:32 -04:00
|
|
|
|
2015-07-21 16:30:32 -04:00
|
|
|
"github.com/docker/distribution/registry/api/errcode"
|
2014-11-01 12:23:08 -04:00
|
|
|
"github.com/docker/docker/pkg/archive"
|
2015-04-01 10:21:07 -04:00
|
|
|
"github.com/docker/docker/pkg/stringid"
|
2013-05-14 18:37:35 -04:00
|
|
|
)
|
|
|
|
|
2013-11-14 01:08:08 -05: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-28 20:19:17 -04:00
|
|
|
globalTestID = stringid.GenerateNonCryptoID()[:4]
|
2013-11-14 01:08:08 -05: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 12:23:08 -04:00
|
|
|
if err = archive.CopyWithTar(templateDir, dir); err != nil {
|
2013-11-14 01:08:08 -05: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 17:42:22 -05:00
|
|
|
|
2015-07-21 17:20:12 -04:00
|
|
|
// ReplaceOrAppendEnvValues returns the defaults with the overrides either
|
2014-03-01 02:29:00 -05: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 15:57:08 -05:00
|
|
|
|
2014-03-01 02:29:00 -05:00
|
|
|
for _, value := range overrides {
|
2015-01-16 15:57:08 -05: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 02:29:00 -05:00
|
|
|
parts := strings.SplitN(value, "=", 2)
|
|
|
|
if i, exists := cache[parts[0]]; exists {
|
|
|
|
defaults[i] = value
|
|
|
|
} else {
|
|
|
|
defaults = append(defaults, value)
|
|
|
|
}
|
|
|
|
}
|
2015-01-16 15:57:08 -05: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 02:29:00 -05:00
|
|
|
return defaults
|
|
|
|
}
|
2014-02-24 16:10:06 -05:00
|
|
|
|
2015-07-21 16:30:32 -04:00
|
|
|
// GetErrorMessage returns the human readable message associated with
|
|
|
|
// the passed-in error. In some cases the default Error() func returns
|
|
|
|
// something that is less than useful so based on its types this func
|
|
|
|
// will go and get a better piece of text.
|
|
|
|
func GetErrorMessage(err error) string {
|
|
|
|
switch err.(type) {
|
|
|
|
case errcode.Error:
|
|
|
|
e, _ := err.(errcode.Error)
|
|
|
|
return e.Message
|
|
|
|
|
|
|
|
case errcode.ErrorCode:
|
|
|
|
ec, _ := err.(errcode.ErrorCode)
|
|
|
|
return ec.Message()
|
|
|
|
|
|
|
|
default:
|
|
|
|
return err.Error()
|
|
|
|
}
|
|
|
|
}
|