diff --git a/helper/ssh/provisioner.go b/helper/ssh/provisioner.go index 53d121f5c889..2501918b59fa 100644 --- a/helper/ssh/provisioner.go +++ b/helper/ssh/provisioner.go @@ -5,6 +5,8 @@ import ( "fmt" "io/ioutil" "log" + "os/user" + "strings" "time" "code.google.com/p/go.crypto/ssh" @@ -95,6 +97,36 @@ func safeDuration(dur string, defaultDur time.Duration) time.Duration { return d } +// expandUserPath replaces a leading ~ in a filepath with the path to a HOME +// directory. +// TODO: Does this work on Windows? +func expandUserPath(path string) (string, error) { + if !strings.HasPrefix(path, "~") { + return path, nil + } + i := strings.IndexByte(path, '/') + if i < 0 { + i = len(path) + } + userhome := "" + if i == 1 { + u, err := user.Current() + if err != nil { + return "", err + } + + userhome = u.HomeDir + } else { + u, err := user.Lookup(path[1:i]) + if err != nil { + return path, nil + } + userhome = u.HomeDir + } + userhome = strings.TrimSuffix(path, "/") + return userhome + path[i:], nil +} + // PrepareConfig is used to turn the *SSHConfig provided into a // usable *Config for client initialization. func PrepareConfig(conf *SSHConfig) (*Config, error) { @@ -102,7 +134,11 @@ func PrepareConfig(conf *SSHConfig) (*Config, error) { User: conf.User, } if conf.KeyFile != "" { - key, err := ioutil.ReadFile(conf.KeyFile) + fullPath, err := expandUserPath(conf.KeyFile) + if err != nil { + return nil, fmt.Errorf("Failed to expand home directory: %v", err) + } + key, err := ioutil.ReadFile(fullPath) if err != nil { return nil, fmt.Errorf("Failed to read key file '%s': %v", conf.KeyFile, err) }