mirror of https://github.com/docker/docs.git
269 lines
6.5 KiB
Go
269 lines
6.5 KiB
Go
package commands
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"text/template"
|
|
|
|
"github.com/docker/machine/commands/mcndirs"
|
|
"github.com/docker/machine/libmachine"
|
|
"github.com/docker/machine/libmachine/check"
|
|
"github.com/docker/machine/libmachine/log"
|
|
"github.com/docker/machine/libmachine/shell"
|
|
)
|
|
|
|
const (
|
|
envTmpl = `{{ .Prefix }}DOCKER_TLS_VERIFY{{ .Delimiter }}{{ .DockerTLSVerify }}{{ .Suffix }}{{ .Prefix }}DOCKER_HOST{{ .Delimiter }}{{ .DockerHost }}{{ .Suffix }}{{ .Prefix }}DOCKER_CERT_PATH{{ .Delimiter }}{{ .DockerCertPath }}{{ .Suffix }}{{ .Prefix }}DOCKER_MACHINE_NAME{{ .Delimiter }}{{ .MachineName }}{{ .Suffix }}{{ if .NoProxyVar }}{{ .Prefix }}{{ .NoProxyVar }}{{ .Delimiter }}{{ .NoProxyValue }}{{ .Suffix }}{{end}}{{ .UsageHint }}`
|
|
)
|
|
|
|
var (
|
|
errImproperUnsetEnvArgs = errors.New("Error: Expected no machine name when the -u flag is present")
|
|
defaultUsageHinter UsageHintGenerator
|
|
)
|
|
|
|
func init() {
|
|
defaultUsageHinter = &EnvUsageHintGenerator{}
|
|
}
|
|
|
|
type ShellConfig struct {
|
|
Prefix string
|
|
Delimiter string
|
|
Suffix string
|
|
DockerCertPath string
|
|
DockerHost string
|
|
DockerTLSVerify string
|
|
UsageHint string
|
|
MachineName string
|
|
NoProxyVar string
|
|
NoProxyValue string
|
|
}
|
|
|
|
func cmdEnv(c CommandLine, api libmachine.API) error {
|
|
var (
|
|
err error
|
|
shellCfg *ShellConfig
|
|
)
|
|
|
|
// Ensure that log messages always go to stderr when this command is
|
|
// being run (it is intended to be run in a subshell)
|
|
log.SetOutWriter(os.Stderr)
|
|
|
|
if c.Bool("unset") {
|
|
shellCfg, err = shellCfgUnset(c, api)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
shellCfg, err = shellCfgSet(c, api)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return executeTemplateStdout(shellCfg)
|
|
}
|
|
|
|
func shellCfgSet(c CommandLine, api libmachine.API) (*ShellConfig, error) {
|
|
if len(c.Args()) > 1 {
|
|
return nil, ErrExpectedOneMachine
|
|
}
|
|
|
|
target, err := targetHost(c, api)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
host, err := api.Load(target)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
dockerHost, _, err := check.DefaultConnChecker.Check(host, c.Bool("swarm"))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Error checking TLS connection: %s", err)
|
|
}
|
|
|
|
userShell, err := getShell(c.String("shell"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
shellCfg := &ShellConfig{
|
|
DockerCertPath: filepath.Join(mcndirs.GetMachineDir(), host.Name),
|
|
DockerHost: dockerHost,
|
|
DockerTLSVerify: "1",
|
|
UsageHint: defaultUsageHinter.GenerateUsageHint(userShell, os.Args),
|
|
MachineName: host.Name,
|
|
}
|
|
|
|
if c.Bool("no-proxy") {
|
|
ip, err := host.Driver.GetIP()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Error getting host IP: %s", err)
|
|
}
|
|
|
|
noProxyVar, noProxyValue := findNoProxyFromEnv()
|
|
|
|
// add the docker host to the no_proxy list idempotently
|
|
switch {
|
|
case noProxyValue == "":
|
|
noProxyValue = ip
|
|
case strings.Contains(noProxyValue, ip):
|
|
//ip already in no_proxy list, nothing to do
|
|
default:
|
|
noProxyValue = fmt.Sprintf("%s,%s", noProxyValue, ip)
|
|
}
|
|
|
|
shellCfg.NoProxyVar = noProxyVar
|
|
shellCfg.NoProxyValue = noProxyValue
|
|
}
|
|
|
|
switch userShell {
|
|
case "fish":
|
|
shellCfg.Prefix = "set -gx "
|
|
shellCfg.Suffix = "\";\n"
|
|
shellCfg.Delimiter = " \""
|
|
case "powershell":
|
|
shellCfg.Prefix = "$Env:"
|
|
shellCfg.Suffix = "\"\n"
|
|
shellCfg.Delimiter = " = \""
|
|
case "cmd":
|
|
shellCfg.Prefix = "SET "
|
|
shellCfg.Suffix = "\n"
|
|
shellCfg.Delimiter = "="
|
|
case "tcsh":
|
|
shellCfg.Prefix = "setenv "
|
|
shellCfg.Suffix = "\";\n"
|
|
shellCfg.Delimiter = " \""
|
|
case "emacs":
|
|
shellCfg.Prefix = "(setenv \""
|
|
shellCfg.Suffix = "\")\n"
|
|
shellCfg.Delimiter = "\" \""
|
|
default:
|
|
shellCfg.Prefix = "export "
|
|
shellCfg.Suffix = "\"\n"
|
|
shellCfg.Delimiter = "=\""
|
|
}
|
|
|
|
return shellCfg, nil
|
|
}
|
|
|
|
func shellCfgUnset(c CommandLine, api libmachine.API) (*ShellConfig, error) {
|
|
if len(c.Args()) != 0 {
|
|
return nil, errImproperUnsetEnvArgs
|
|
}
|
|
|
|
userShell, err := getShell(c.String("shell"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
shellCfg := &ShellConfig{
|
|
UsageHint: defaultUsageHinter.GenerateUsageHint(userShell, os.Args),
|
|
}
|
|
|
|
if c.Bool("no-proxy") {
|
|
shellCfg.NoProxyVar, shellCfg.NoProxyValue = findNoProxyFromEnv()
|
|
}
|
|
|
|
switch userShell {
|
|
case "fish":
|
|
shellCfg.Prefix = "set -e "
|
|
shellCfg.Suffix = ";\n"
|
|
shellCfg.Delimiter = ""
|
|
case "powershell":
|
|
shellCfg.Prefix = `Remove-Item Env:\\`
|
|
shellCfg.Suffix = "\n"
|
|
shellCfg.Delimiter = ""
|
|
case "cmd":
|
|
shellCfg.Prefix = "SET "
|
|
shellCfg.Suffix = "\n"
|
|
shellCfg.Delimiter = "="
|
|
case "emacs":
|
|
shellCfg.Prefix = "(setenv \""
|
|
shellCfg.Suffix = ")\n"
|
|
shellCfg.Delimiter = "\" nil"
|
|
case "tcsh":
|
|
shellCfg.Prefix = "unsetenv "
|
|
shellCfg.Suffix = ";\n"
|
|
shellCfg.Delimiter = ""
|
|
default:
|
|
shellCfg.Prefix = "unset "
|
|
shellCfg.Suffix = "\n"
|
|
shellCfg.Delimiter = ""
|
|
}
|
|
|
|
return shellCfg, nil
|
|
}
|
|
|
|
func executeTemplateStdout(shellCfg *ShellConfig) error {
|
|
t := template.New("envConfig")
|
|
tmpl, err := t.Parse(envTmpl)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return tmpl.Execute(os.Stdout, shellCfg)
|
|
}
|
|
|
|
func getShell(userShell string) (string, error) {
|
|
if userShell != "" {
|
|
return userShell, nil
|
|
}
|
|
return shell.Detect()
|
|
}
|
|
|
|
func findNoProxyFromEnv() (string, string) {
|
|
// first check for an existing lower case no_proxy var
|
|
noProxyVar := "no_proxy"
|
|
noProxyValue := os.Getenv("no_proxy")
|
|
|
|
// otherwise default to allcaps HTTP_PROXY
|
|
if noProxyValue == "" {
|
|
noProxyVar = "NO_PROXY"
|
|
noProxyValue = os.Getenv("NO_PROXY")
|
|
}
|
|
return noProxyVar, noProxyValue
|
|
}
|
|
|
|
type UsageHintGenerator interface {
|
|
GenerateUsageHint(string, []string) string
|
|
}
|
|
|
|
type EnvUsageHintGenerator struct{}
|
|
|
|
func (g *EnvUsageHintGenerator) GenerateUsageHint(userShell string, args []string) string {
|
|
cmd := ""
|
|
comment := "#"
|
|
|
|
dockerMachinePath := args[0]
|
|
if strings.Contains(dockerMachinePath, " ") || strings.Contains(dockerMachinePath, `\`) {
|
|
args[0] = fmt.Sprintf("\"%s\"", dockerMachinePath)
|
|
}
|
|
|
|
commandLine := strings.Join(args, " ")
|
|
|
|
switch userShell {
|
|
case "fish":
|
|
cmd = fmt.Sprintf("eval (%s)", commandLine)
|
|
case "powershell":
|
|
cmd = fmt.Sprintf("& %s | Invoke-Expression", commandLine)
|
|
case "cmd":
|
|
cmd = fmt.Sprintf("\t@FOR /f \"tokens=*\" %%i IN ('%s') DO @%%i", commandLine)
|
|
comment = "REM"
|
|
case "emacs":
|
|
cmd = fmt.Sprintf("(with-temp-buffer (shell-command \"%s\" (current-buffer)) (eval-buffer))", commandLine)
|
|
comment = ";;"
|
|
case "tcsh":
|
|
cmd = fmt.Sprintf("eval `%s`", commandLine)
|
|
comment = ":"
|
|
default:
|
|
cmd = fmt.Sprintf("eval $(%s)", commandLine)
|
|
}
|
|
|
|
return fmt.Sprintf("%s Run this command to configure your shell: \n%s %s\n", comment, comment, cmd)
|
|
}
|