Merge pull request #6527 from tstromberg/powershell-env

Bug-compatible refactor of docker-env + output tests
pull/6540/head^2
Thomas Strömberg 2020-02-06 21:57:25 -08:00 committed by GitHub
commit 10ef863f7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 382 additions and 567 deletions

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright 2020 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -21,25 +21,29 @@ package cmd
import (
"fmt"
"io"
"net"
"os"
"strconv"
"strings"
"text/template"
"github.com/docker/machine/libmachine"
"github.com/docker/machine/libmachine/drivers"
"github.com/docker/machine/libmachine/host"
"github.com/docker/machine/libmachine/log"
"github.com/docker/machine/libmachine/shell"
"github.com/docker/machine/libmachine/state"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"k8s.io/minikube/pkg/drivers/kic"
"k8s.io/minikube/pkg/drivers/kic/oci"
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/driver"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/localpath"
"k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/out"
)
var envTmpl = fmt.Sprintf("{{ .Prefix }}%s{{ .Delimiter }}{{ .DockerTLSVerify }}{{ .Suffix }}{{ .Prefix }}%s{{ .Delimiter }}{{ .DockerHost }}{{ .Suffix }}{{ .Prefix }}%s{{ .Delimiter }}{{ .DockerCertPath }}{{ .Suffix }}{{ .Prefix }}%s{{ .Delimiter }}{{ .MinikubeDockerdProfile }}{{ .Suffix }}{{ if .NoProxyVar }}{{ .Prefix }}{{ .NoProxyVar }}{{ .Delimiter }}{{ .NoProxyValue }}{{ .Suffix }}{{end}}{{ .UsageHint }}", constants.DockerTLSVerifyEnv, constants.DockerHostEnv, constants.DockerCertPathEnv, constants.MinikubeActiveDockerdEnv)
@ -108,18 +112,9 @@ var (
noProxy bool
forceShell string
unset bool
defaultShellDetector ShellDetector
defaultNoProxyGetter NoProxyGetter
)
// ShellDetector detects shell
type ShellDetector interface {
GetShell(string) (string, error)
}
// LibmachineShellDetector detects shell, using libmachine
type LibmachineShellDetector struct{}
// NoProxyGetter gets the no_proxy variable
type NoProxyGetter interface {
GetNoProxyVar() (string, string)
@ -128,7 +123,7 @@ type NoProxyGetter interface {
// EnvNoProxyGetter gets the no_proxy variable, using environment
type EnvNoProxyGetter struct{}
func generateUsageHint(profile string, userShell string) string {
func generateUsageHint(profile, sh string) string {
const usgPlz = "Please run command bellow to point your shell to minikube's docker-daemon :"
var usgCmd = fmt.Sprintf("minikube -p %s docker-env", profile)
var usageHintMap = map[string]string{
@ -154,148 +149,108 @@ REM @FOR /f "tokens=*" %%i IN ('%s') DO @%%i
`, usgPlz, usgCmd),
}
hint, ok := usageHintMap[userShell]
hint, ok := usageHintMap[sh]
if !ok {
return usageHintMap["bash"]
}
return hint
}
func shellCfgSet(api libmachine.API) (*ShellConfig, error) {
envMap, err := cluster.GetNodeDockerEnv(api)
if err != nil {
return nil, err
}
userShell, err := defaultShellDetector.GetShell(forceShell)
if err != nil {
return nil, err
}
shellCfg := &ShellConfig{
// shellCfgSet generates context variables for "docker-env"
func shellCfgSet(ec EnvConfig, envMap map[string]string) *ShellConfig {
s := &ShellConfig{
DockerCertPath: envMap[constants.DockerCertPathEnv],
DockerHost: envMap[constants.DockerHostEnv],
DockerTLSVerify: envMap[constants.DockerTLSVerifyEnv],
MinikubeDockerdProfile: envMap[constants.MinikubeActiveDockerdEnv],
UsageHint: generateUsageHint(viper.GetString(config.MachineProfile), userShell),
UsageHint: generateUsageHint(ec.profile, ec.shell),
}
if noProxy {
host, err := api.Load(viper.GetString(config.MachineProfile))
if err != nil {
return nil, errors.Wrap(err, "Error getting IP")
}
ip, err := host.Driver.GetIP()
if err != nil {
return nil, errors.Wrap(err, "Error getting host IP")
}
if ec.noProxy {
noProxyVar, noProxyValue := defaultNoProxyGetter.GetNoProxyVar()
// add the docker host to the no_proxy list idempotently
switch {
case noProxyValue == "":
noProxyValue = ip
case strings.Contains(noProxyValue, ip):
noProxyValue = ec.hostIP
case strings.Contains(noProxyValue, ec.hostIP):
// ip already in no_proxy list, nothing to do
default:
noProxyValue = fmt.Sprintf("%s,%s", noProxyValue, ip)
noProxyValue = fmt.Sprintf("%s,%s", noProxyValue, ec.hostIP)
}
shellCfg.NoProxyVar = noProxyVar
shellCfg.NoProxyValue = noProxyValue
s.NoProxyVar = noProxyVar
s.NoProxyValue = noProxyValue
}
switch userShell {
switch ec.shell {
case "fish":
shellCfg.Prefix = fishSetPfx
shellCfg.Suffix = fishSetSfx
shellCfg.Delimiter = fishSetDelim
s.Prefix = fishSetPfx
s.Suffix = fishSetSfx
s.Delimiter = fishSetDelim
case "powershell":
shellCfg.Prefix = psSetPfx
shellCfg.Suffix = psSetSfx
shellCfg.Delimiter = psSetDelim
s.Prefix = psSetPfx
s.Suffix = psSetSfx
s.Delimiter = psSetDelim
case "cmd":
shellCfg.Prefix = cmdSetPfx
shellCfg.Suffix = cmdSetSfx
shellCfg.Delimiter = cmdSetDelim
s.Prefix = cmdSetPfx
s.Suffix = cmdSetSfx
s.Delimiter = cmdSetDelim
case "emacs":
shellCfg.Prefix = emacsSetPfx
shellCfg.Suffix = emacsSetSfx
shellCfg.Delimiter = emacsSetDelim
s.Prefix = emacsSetPfx
s.Suffix = emacsSetSfx
s.Delimiter = emacsSetDelim
case "none":
shellCfg.Prefix = nonePfx
shellCfg.Suffix = noneSfx
shellCfg.Delimiter = noneDelim
shellCfg.UsageHint = ""
s.Prefix = nonePfx
s.Suffix = noneSfx
s.Delimiter = noneDelim
s.UsageHint = ""
default:
shellCfg.Prefix = bashSetPfx
shellCfg.Suffix = bashSetSfx
shellCfg.Delimiter = bashSetDelim
s.Prefix = bashSetPfx
s.Suffix = bashSetSfx
s.Delimiter = bashSetDelim
}
return shellCfg, nil
return s
}
func shellCfgUnset() (*ShellConfig, error) {
userShell, err := defaultShellDetector.GetShell(forceShell)
if err != nil {
return nil, err
// shellCfgUnset generates context variables for "docker-env -u"
func shellCfgUnset(ec EnvConfig) *ShellConfig {
s := &ShellConfig{
UsageHint: generateUsageHint(ec.profile, ec.shell),
}
shellCfg := &ShellConfig{
UsageHint: generateUsageHint(viper.GetString(config.MachineProfile), userShell),
if ec.noProxy {
s.NoProxyVar, s.NoProxyValue = defaultNoProxyGetter.GetNoProxyVar()
}
if noProxy {
shellCfg.NoProxyVar, shellCfg.NoProxyValue = defaultNoProxyGetter.GetNoProxyVar()
}
switch userShell {
switch ec.shell {
case "fish":
shellCfg.Prefix = fishUnsetPfx
shellCfg.Suffix = fishUnsetSfx
shellCfg.Delimiter = fishUnsetDelim
s.Prefix = fishUnsetPfx
s.Suffix = fishUnsetSfx
s.Delimiter = fishUnsetDelim
case "powershell":
shellCfg.Prefix = psUnsetPfx
shellCfg.Suffix = psUnsetSfx
shellCfg.Delimiter = psUnsetDelim
s.Prefix = psUnsetPfx
s.Suffix = psUnsetSfx
s.Delimiter = psUnsetDelim
case "cmd":
shellCfg.Prefix = cmdUnsetPfx
shellCfg.Suffix = cmdUnsetSfx
shellCfg.Delimiter = cmdUnsetDelim
s.Prefix = cmdUnsetPfx
s.Suffix = cmdUnsetSfx
s.Delimiter = cmdUnsetDelim
case "emacs":
shellCfg.Prefix = emacsUnsetPfx
shellCfg.Suffix = emacsUnsetSfx
shellCfg.Delimiter = emacsUnsetDelim
s.Prefix = emacsUnsetPfx
s.Suffix = emacsUnsetSfx
s.Delimiter = emacsUnsetDelim
case "none":
shellCfg.Prefix = nonePfx
shellCfg.Suffix = noneSfx
shellCfg.Delimiter = noneDelim
shellCfg.UsageHint = ""
s.Prefix = nonePfx
s.Suffix = noneSfx
s.Delimiter = noneDelim
s.UsageHint = ""
default:
shellCfg.Prefix = bashUnsetPfx
shellCfg.Suffix = bashUnsetSfx
shellCfg.Delimiter = bashUnsetDelim
s.Prefix = bashUnsetPfx
s.Suffix = bashUnsetSfx
s.Delimiter = bashUnsetDelim
}
return shellCfg, nil
}
func executeTemplateStdout(shellCfg *ShellConfig) error {
tmpl := template.Must(template.New("envConfig").Parse(envTmpl))
return tmpl.Execute(os.Stdout, shellCfg)
}
// GetShell detects the shell
func (LibmachineShellDetector) GetShell(userShell string) (string, error) {
if userShell != "" {
return userShell, nil
}
return shell.Detect()
return s
}
// GetNoProxyVar gets the no_proxy var
@ -312,30 +267,18 @@ func (EnvNoProxyGetter) GetNoProxyVar() (string, string) {
return noProxyVar, noProxyValue
}
// same as drivers.RunSSHCommandFromDriver, but allows errors
func runSSHCommandFromDriver(d drivers.Driver, command string) (string, error) {
// isDockerActive checks if Docker is active
func isDockerActive(d drivers.Driver) (bool, error) {
client, err := drivers.GetSSHClientFromDriver(d)
if err != nil {
return "", err
return false, err
}
output, err := client.Output("sudo systemctl is-active docker")
if err != nil {
return false, err
}
log.Debugf("About to run SSH command:\n%s", command)
output, err := client.Output(command)
log.Debugf("SSH cmd err, output: %v: %s", err, output)
return output, err
}
// same as host.RunSSHCommand, but allows errors
func runSSHCommand(h *host.Host, command string) (string, error) {
return runSSHCommandFromDriver(h.Driver, command)
}
// GetDockerActive checks if Docker is active
func GetDockerActive(host *host.Host) (bool, error) {
statusCmd := `sudo systemctl is-active docker`
status, err := runSSHCommand(host, statusCmd)
// systemd returns error code on inactive
s := strings.TrimSpace(status)
s := strings.TrimSpace(output)
return err == nil && s == "active", nil
}
@ -350,7 +293,9 @@ var dockerEnvCmd = &cobra.Command{
exit.WithError("Error getting client", err)
}
defer api.Close()
cc, err := config.Load(viper.GetString(config.MachineProfile))
profile := viper.GetString(config.MachineProfile)
cc, err := config.Load(profile)
if err != nil {
exit.WithError("Error getting config", err)
}
@ -361,43 +306,108 @@ var dockerEnvCmd = &cobra.Command{
if host.Driver.DriverName() == driver.None {
exit.UsageT(`'none' driver does not support 'minikube docker-env' command`)
}
hostSt, err := cluster.GetHostStatus(api, cc.Name)
if err != nil {
exit.WithError("Error getting host status", err)
}
if hostSt != state.Running.String() {
exit.WithCodeT(exit.Unavailable, `The docker host is currently not running`)
exit.WithCodeT(exit.Unavailable, `'{{.profile}}' is not running`, out.V{"profile": profile})
}
docker, err := GetDockerActive(host)
ok, err := isDockerActive(host.Driver)
if err != nil {
exit.WithError("Error getting service status", err)
}
if !docker {
exit.WithCodeT(exit.Unavailable, `The docker service is currently not active`)
if !ok {
exit.WithCodeT(exit.Unavailable, `The docker service within '{{.profile}}' is not active`, out.V{"profile": profile})
}
var shellCfg *ShellConfig
hostIP, err := host.Driver.GetIP()
if err != nil {
exit.WithError("Error getting host IP", err)
}
ec := EnvConfig{
profile: profile,
driver: host.DriverName,
shell: forceShell,
hostIP: hostIP,
certsDir: localpath.MakeMiniPath("certs"),
noProxy: noProxy,
}
if ec.shell == "" {
ec.shell, err = shell.Detect()
if err != nil {
exit.WithError("Error detecting shell", err)
}
}
if unset {
shellCfg, err = shellCfgUnset()
if err != nil {
exit.WithError("Error unsetting shell variables", err)
}
} else {
shellCfg, err = shellCfgSet(api)
if err != nil {
exit.WithError("Error setting shell variables", err)
if err := unsetScript(ec, os.Stdout); err != nil {
exit.WithError("Error generating unset output", err)
}
return
}
if err := executeTemplateStdout(shellCfg); err != nil {
exit.WithError("Error executing template", err)
if err := setScript(ec, os.Stdout); err != nil {
exit.WithError("Error generating set output", err)
}
},
}
// EnvConfig encapsulates all external inputs into shell generation
type EnvConfig struct {
profile string
shell string
driver string
hostIP string
certsDir string
noProxy bool
}
// setScript writes out a shell-compatible 'docker-env' script
func setScript(ec EnvConfig, w io.Writer) error {
tmpl := template.Must(template.New("envConfig").Parse(envTmpl))
envVars, err := dockerEnvVars(ec)
if err != nil {
return err
}
return tmpl.Execute(w, shellCfgSet(ec, envVars))
}
// setScript writes out a shell-compatible 'docker-env unset' script
func unsetScript(ec EnvConfig, w io.Writer) error {
tmpl := template.Must(template.New("envConfig").Parse(envTmpl))
return tmpl.Execute(w, shellCfgUnset(ec))
}
// dockerURL returns a the docker endpoint URL for an ip/port pair.
func dockerURL(ip string, port int) string {
return fmt.Sprintf("tcp://%s", net.JoinHostPort(ip, strconv.Itoa(port)))
}
// dockerEnvVars gets the necessary docker env variables to allow the use of minikube's docker daemon
func dockerEnvVars(ec EnvConfig) (map[string]string, error) {
env := map[string]string{
constants.DockerTLSVerifyEnv: "1",
constants.DockerHostEnv: dockerURL(ec.hostIP, constants.DockerDaemonPort),
constants.DockerCertPathEnv: ec.certsDir,
constants.MinikubeActiveDockerdEnv: ec.profile,
}
if driver.IsKIC(ec.driver) { // for kic we need to find out what port docker allocated during creation
port, err := oci.HostPortBinding(ec.driver, ec.profile, constants.DockerDaemonPort)
if err != nil {
return nil, errors.Wrapf(err, "get hostbind port for %d", constants.DockerDaemonPort)
}
env[constants.DockerCertPathEnv] = dockerURL(kic.DefaultBindIPV4, port)
}
return env, nil
}
func init() {
defaultShellDetector = &LibmachineShellDetector{}
defaultNoProxyGetter = &EnvNoProxyGetter{}
dockerEnvCmd.Flags().BoolVar(&noProxy, "no-proxy", false, "Add machine IP to NO_PROXY environment variable")
dockerEnvCmd.Flags().StringVar(&forceShell, "shell", "", "Force environment to be configured for a specified shell: [fish, cmd, powershell, tcsh, bash, zsh], default is auto-detect")

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright 2020 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -17,25 +17,12 @@ limitations under the License.
package cmd
import (
"reflect"
"bytes"
"testing"
"github.com/docker/machine/libmachine/host"
"github.com/spf13/viper"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/localpath"
"k8s.io/minikube/pkg/minikube/tests"
"github.com/google/go-cmp/cmp"
)
type FakeShellDetector struct {
Shell string
}
func (f FakeShellDetector) GetShell(_ string) (string, error) {
return f.Shell, nil
}
type FakeNoProxyGetter struct {
NoProxyVar string
NoProxyValue string
@ -45,297 +32,250 @@ func (f FakeNoProxyGetter) GetNoProxyVar() (string, string) {
return f.NoProxyVar, f.NoProxyValue
}
var defaultAPI = &tests.MockAPI{
FakeStore: tests.FakeStore{
Hosts: map[string]*host.Host{
constants.DefaultMachineName: {
Name: constants.DefaultMachineName,
Driver: &tests.MockDriver{},
},
},
},
}
// Most of the shell cfg isn't configurable
func newShellCfg(shell, prefix, suffix, delim string) *ShellConfig {
return &ShellConfig{
DockerCertPath: localpath.MakeMiniPath("certs"),
DockerTLSVerify: "1",
DockerHost: "tcp://127.0.0.1:2376",
UsageHint: generateUsageHint("minikube", shell),
Prefix: prefix,
Suffix: suffix,
Delimiter: delim,
MinikubeDockerdProfile: "minikube",
}
}
func TestShellCfgSet(t *testing.T) {
func TestGenerateScripts(t *testing.T) {
var tests = []struct {
description string
api *tests.MockAPI
shell string
noProxyVar string
noProxyValue string
expectedShellCfg *ShellConfig
shouldErr bool
noProxyFlag bool
config EnvConfig
noProxyGetter *FakeNoProxyGetter
wantSet string
wantUnset string
}{
{
description: "no host specified",
api: &tests.MockAPI{
FakeStore: tests.FakeStore{
Hosts: make(map[string]*host.Host),
},
},
shell: "bash",
expectedShellCfg: nil,
shouldErr: true,
EnvConfig{profile: "bash", shell: "bash", driver: "kvm2", hostIP: "127.0.0.1", certsDir: "/certs"},
nil,
`export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://127.0.0.1:2376"
export DOCKER_CERT_PATH="/certs"
export MINIKUBE_ACTIVE_DOCKERD="bash"
# Please run command bellow to point your shell to minikube's docker-daemon :
# eval $(minikube -p bash docker-env)
`,
`unset DOCKER_TLS_VERIFY
unset DOCKER_HOST
unset DOCKER_CERT_PATH
unset MINIKUBE_ACTIVE_DOCKERD
# Please run command bellow to point your shell to minikube's docker-daemon :
# eval $(minikube -p bash docker-env)
`,
},
{
description: "default",
api: defaultAPI,
shell: "bash",
expectedShellCfg: newShellCfg("", bashSetPfx, bashSetSfx, bashSetDelim),
shouldErr: false,
EnvConfig{profile: "ipv6", shell: "bash", driver: "kvm2", hostIP: "fe80::215:5dff:fe00:a903", certsDir: "/certs"},
nil,
`export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://[fe80::215:5dff:fe00:a903]:2376"
export DOCKER_CERT_PATH="/certs"
export MINIKUBE_ACTIVE_DOCKERD="ipv6"
# Please run command bellow to point your shell to minikube's docker-daemon :
# eval $(minikube -p ipv6 docker-env)
`,
`unset DOCKER_TLS_VERIFY
unset DOCKER_HOST
unset DOCKER_CERT_PATH
unset MINIKUBE_ACTIVE_DOCKERD
# Please run command bellow to point your shell to minikube's docker-daemon :
# eval $(minikube -p ipv6 docker-env)
`,
},
{
description: "bash",
api: defaultAPI,
shell: "bash",
expectedShellCfg: newShellCfg("bash", bashSetPfx, bashSetSfx, bashSetDelim),
shouldErr: false,
EnvConfig{profile: "fish", shell: "fish", driver: "kvm2", hostIP: "127.0.0.1", certsDir: "/certs"},
nil,
`set -gx DOCKER_TLS_VERIFY "1";
set -gx DOCKER_HOST "tcp://127.0.0.1:2376";
set -gx DOCKER_CERT_PATH "/certs";
set -gx MINIKUBE_ACTIVE_DOCKERD "fish";
# Please run command bellow to point your shell to minikube's docker-daemon :
# eval (minikube -p fish docker-env)
`,
`set -e DOCKER_TLS_VERIFY;
set -e DOCKER_HOST;
set -e DOCKER_CERT_PATH;
set -e MINIKUBE_ACTIVE_DOCKERD;
# Please run command bellow to point your shell to minikube's docker-daemon :
# eval (minikube -p fish docker-env)
`,
},
{
description: "fish",
api: defaultAPI,
shell: "fish",
expectedShellCfg: newShellCfg("fish", fishSetPfx, fishSetSfx, fishSetDelim),
shouldErr: false,
EnvConfig{profile: "powershell", shell: "powershell", driver: "hyperv", hostIP: "192.168.0.1", certsDir: "/certs"},
nil,
`$Env:DOCKER_TLS_VERIFY = "1"
$Env:DOCKER_HOST = "tcp://192.168.0.1:2376"
$Env:DOCKER_CERT_PATH = "/certs"
$Env:MINIKUBE_ACTIVE_DOCKERD = "powershell"
# Please run command bellow to point your shell to minikube's docker-daemon :
# & minikube -p powershell docker-env | Invoke-Expression
`,
`Remove-Item Env:\\DOCKER_TLS_VERIFY
Remove-Item Env:\\DOCKER_HOST
Remove-Item Env:\\DOCKER_CERT_PATH
Remove-Item Env:\\MINIKUBE_ACTIVE_DOCKERD
# Please run command bellow to point your shell to minikube's docker-daemon :
# & minikube -p powershell docker-env | Invoke-Expression
`,
},
{
description: "powershell",
api: defaultAPI,
shell: "powershell",
expectedShellCfg: newShellCfg("powershell", psSetPfx, psSetSfx, psSetDelim),
shouldErr: false,
EnvConfig{profile: "cmd", shell: "cmd", driver: "hyperv", hostIP: "192.168.0.1", certsDir: "/certs"},
nil,
`SET DOCKER_TLS_VERIFY=1
SET DOCKER_HOST=tcp://192.168.0.1:2376
SET DOCKER_CERT_PATH=/certs
SET MINIKUBE_ACTIVE_DOCKERD=cmd
REM Please run command bellow to point your shell to minikube's docker-daemon :
REM @FOR /f "tokens=*" %i IN ('minikube -p cmd docker-env') DO @%i
`,
`SET DOCKER_TLS_VERIFY=
SET DOCKER_HOST=
SET DOCKER_CERT_PATH=
SET MINIKUBE_ACTIVE_DOCKERD=
REM Please run command bellow to point your shell to minikube's docker-daemon :
REM @FOR /f "tokens=*" %i IN ('minikube -p cmd docker-env') DO @%i
`,
},
{
description: "cmd",
api: defaultAPI,
shell: "cmd",
expectedShellCfg: newShellCfg("cmd", cmdSetPfx, cmdSetSfx, cmdSetDelim),
shouldErr: false,
EnvConfig{profile: "emacs", shell: "emacs", driver: "hyperv", hostIP: "192.168.0.1", certsDir: "/certs"},
nil,
`(setenv "DOCKER_TLS_VERIFY" "1")
(setenv "DOCKER_HOST" "tcp://192.168.0.1:2376")
(setenv "DOCKER_CERT_PATH" "/certs")
(setenv "MINIKUBE_ACTIVE_DOCKERD" "emacs")
;; Please run command bellow to point your shell to minikube's docker-daemon :
;; (with-temp-buffer (shell-command "minikube -p emacs docker-env" (current-buffer)) (eval-buffer))
`,
`(setenv "DOCKER_TLS_VERIFY" nil)
(setenv "DOCKER_HOST" nil)
(setenv "DOCKER_CERT_PATH" nil)
(setenv "MINIKUBE_ACTIVE_DOCKERD" nil)
;; Please run command bellow to point your shell to minikube's docker-daemon :
;; (with-temp-buffer (shell-command "minikube -p emacs docker-env" (current-buffer)) (eval-buffer))
`,
},
{
description: "emacs",
api: defaultAPI,
shell: "emacs",
expectedShellCfg: newShellCfg("emacs", emacsSetPfx, emacsSetSfx, emacsSetDelim),
shouldErr: false,
EnvConfig{profile: "bash-no-proxy", shell: "bash", driver: "kvm2", hostIP: "127.0.0.1", certsDir: "/certs", noProxy: true},
&FakeNoProxyGetter{"NO_PROXY", "127.0.0.1"},
`export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://127.0.0.1:2376"
export DOCKER_CERT_PATH="/certs"
export MINIKUBE_ACTIVE_DOCKERD="bash-no-proxy"
export NO_PROXY="127.0.0.1"
# Please run command bellow to point your shell to minikube's docker-daemon :
# eval $(minikube -p bash-no-proxy docker-env)
`,
`unset DOCKER_TLS_VERIFY
unset DOCKER_HOST
unset DOCKER_CERT_PATH
unset MINIKUBE_ACTIVE_DOCKERD
unset NO_PROXY127.0.0.1
# Please run command bellow to point your shell to minikube's docker-daemon :
# eval $(minikube -p bash-no-proxy docker-env)
`,
},
{
description: "no proxy add uppercase",
api: defaultAPI,
shell: "bash",
noProxyVar: "NO_PROXY",
noProxyValue: "",
noProxyFlag: true,
expectedShellCfg: &ShellConfig{
DockerCertPath: localpath.MakeMiniPath("certs"),
DockerTLSVerify: "1",
DockerHost: "tcp://127.0.0.1:2376",
UsageHint: generateUsageHint("minikube", "bash"),
Prefix: bashSetPfx,
Suffix: bashSetSfx,
Delimiter: bashSetDelim,
NoProxyVar: "NO_PROXY",
NoProxyValue: "127.0.0.1",
MinikubeDockerdProfile: "minikube",
},
EnvConfig{profile: "bash-no-proxy-lower", shell: "bash", driver: "kvm2", hostIP: "127.0.0.1", certsDir: "/certs", noProxy: true},
&FakeNoProxyGetter{"no_proxy", "127.0.0.1"},
`export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://127.0.0.1:2376"
export DOCKER_CERT_PATH="/certs"
export MINIKUBE_ACTIVE_DOCKERD="bash-no-proxy-lower"
export no_proxy="127.0.0.1"
# Please run command bellow to point your shell to minikube's docker-daemon :
# eval $(minikube -p bash-no-proxy-lower docker-env)
`,
`unset DOCKER_TLS_VERIFY
unset DOCKER_HOST
unset DOCKER_CERT_PATH
unset MINIKUBE_ACTIVE_DOCKERD
unset no_proxy127.0.0.1
# Please run command bellow to point your shell to minikube's docker-daemon :
# eval $(minikube -p bash-no-proxy-lower docker-env)
`,
},
{
description: "no proxy add lowercase",
api: defaultAPI,
shell: "bash",
noProxyVar: "no_proxy",
noProxyValue: "",
noProxyFlag: true,
expectedShellCfg: &ShellConfig{
DockerCertPath: localpath.MakeMiniPath("certs"),
DockerTLSVerify: "1",
DockerHost: "tcp://127.0.0.1:2376",
UsageHint: generateUsageHint("minikube", "bash"),
Prefix: bashSetPfx,
Suffix: bashSetSfx,
Delimiter: bashSetDelim,
NoProxyVar: "no_proxy",
NoProxyValue: "127.0.0.1",
MinikubeDockerdProfile: "minikube",
},
EnvConfig{profile: "bash-no-proxy-idempotent", shell: "bash", driver: "kvm2", hostIP: "127.0.0.1", certsDir: "/certs", noProxy: true},
&FakeNoProxyGetter{"no_proxy", "127.0.0.1"},
`export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://127.0.0.1:2376"
export DOCKER_CERT_PATH="/certs"
export MINIKUBE_ACTIVE_DOCKERD="bash-no-proxy-idempotent"
export no_proxy="127.0.0.1"
# Please run command bellow to point your shell to minikube's docker-daemon :
# eval $(minikube -p bash-no-proxy-idempotent docker-env)
`,
`unset DOCKER_TLS_VERIFY
unset DOCKER_HOST
unset DOCKER_CERT_PATH
unset MINIKUBE_ACTIVE_DOCKERD
unset no_proxy127.0.0.1
# Please run command bellow to point your shell to minikube's docker-daemon :
# eval $(minikube -p bash-no-proxy-idempotent docker-env)
`,
},
{
description: "no proxy idempotent",
api: defaultAPI,
shell: "bash",
noProxyVar: "no_proxy",
noProxyValue: "127.0.0.1",
noProxyFlag: true,
expectedShellCfg: &ShellConfig{
DockerCertPath: localpath.MakeMiniPath("certs"),
DockerTLSVerify: "1",
DockerHost: "tcp://127.0.0.1:2376",
UsageHint: generateUsageHint("minikube", "bash"),
Prefix: bashSetPfx,
Suffix: bashSetSfx,
Delimiter: bashSetDelim,
NoProxyVar: "no_proxy",
NoProxyValue: "127.0.0.1",
MinikubeDockerdProfile: "minikube",
},
},
{
description: "no proxy list add",
api: defaultAPI,
shell: "bash",
noProxyVar: "no_proxy",
noProxyValue: "0.0.0.0",
noProxyFlag: true,
expectedShellCfg: &ShellConfig{
DockerCertPath: localpath.MakeMiniPath("certs"),
DockerTLSVerify: "1",
DockerHost: "tcp://127.0.0.1:2376",
UsageHint: generateUsageHint("minikube", "bash"),
Prefix: bashSetPfx,
Suffix: bashSetSfx,
Delimiter: bashSetDelim,
NoProxyVar: "no_proxy",
NoProxyValue: "0.0.0.0,127.0.0.1",
MinikubeDockerdProfile: "minikube",
},
},
{
description: "no proxy list already present",
api: defaultAPI,
shell: "bash",
noProxyVar: "no_proxy",
noProxyValue: "0.0.0.0,127.0.0.1",
noProxyFlag: true,
expectedShellCfg: &ShellConfig{
DockerCertPath: localpath.MakeMiniPath("certs"),
DockerTLSVerify: "1",
DockerHost: "tcp://127.0.0.1:2376",
UsageHint: generateUsageHint("minikube", "bash"),
Prefix: bashSetPfx,
Suffix: bashSetSfx,
Delimiter: bashSetDelim,
NoProxyVar: "no_proxy",
NoProxyValue: "0.0.0.0,127.0.0.1",
MinikubeDockerdProfile: "minikube",
},
EnvConfig{profile: "sh-no-proxy-add", shell: "bash", driver: "kvm2", hostIP: "127.0.0.1", certsDir: "/certs", noProxy: true},
&FakeNoProxyGetter{"NO_PROXY", "192.168.0.1,10.0.0.4"},
`export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://127.0.0.1:2376"
export DOCKER_CERT_PATH="/certs"
export MINIKUBE_ACTIVE_DOCKERD="sh-no-proxy-add"
export NO_PROXY="192.168.0.1,10.0.0.4,127.0.0.1"
# Please run command bellow to point your shell to minikube's docker-daemon :
# eval $(minikube -p sh-no-proxy-add docker-env)
`,
`unset DOCKER_TLS_VERIFY
unset DOCKER_HOST
unset DOCKER_CERT_PATH
unset MINIKUBE_ACTIVE_DOCKERD
unset NO_PROXY192.168.0.1,10.0.0.4
# Please run command bellow to point your shell to minikube's docker-daemon :
# eval $(minikube -p sh-no-proxy-add docker-env)
`,
},
}
for _, tc := range tests {
t.Run(tc.config.profile, func(t *testing.T) {
defaultNoProxyGetter = tc.noProxyGetter
var b []byte
buf := bytes.NewBuffer(b)
if err := setScript(tc.config, buf); err != nil {
t.Errorf("setScript(%+v) error: %v", tc.config, err)
}
got := buf.String()
if diff := cmp.Diff(tc.wantSet, got); diff != "" {
t.Errorf("setScript(%+v) mismatch (-want +got):\n%s\n\nraw output:\n%s\nquoted: %q", tc.config, diff, got, got)
}
for _, test := range tests {
test := test
t.Run(test.description, func(t *testing.T) {
buf = bytes.NewBuffer(b)
if err := unsetScript(tc.config, buf); err != nil {
t.Errorf("unsetScript(%+v) error: %v", tc.config, err)
}
got = buf.String()
if diff := cmp.Diff(tc.wantUnset, got); diff != "" {
t.Errorf("unsetScript(%+v) mismatch (-want +got):\n%s\n\nraw output:\n%s\nquoted: %q", tc.config, diff, got, got)
}
viper.Set(config.MachineProfile, constants.DefaultMachineName)
defaultShellDetector = &FakeShellDetector{test.shell}
defaultNoProxyGetter = &FakeNoProxyGetter{test.noProxyVar, test.noProxyValue}
noProxy = test.noProxyFlag
test.api.T = t
shellCfg, err := shellCfgSet(test.api)
if !reflect.DeepEqual(shellCfg, test.expectedShellCfg) {
t.Errorf("Shell cfgs differ: expected %+v, \n\n got %+v", test.expectedShellCfg, shellCfg)
}
if err != nil && !test.shouldErr {
t.Errorf("Unexpected error occurred: %s, error: %v", test.description, err)
}
if err == nil && test.shouldErr {
t.Errorf("Test didn't return error but should have: %s", test.description)
}
})
}
}
func TestShellCfgUnset(t *testing.T) {
var tests = []struct {
description string
shell string
expectedShellCfg *ShellConfig
}{
{
description: "unset default",
shell: "bash",
expectedShellCfg: &ShellConfig{
Prefix: bashUnsetPfx,
Suffix: bashUnsetSfx,
Delimiter: bashUnsetDelim,
UsageHint: generateUsageHint("minikube", "bash"),
},
},
{
description: "unset bash",
shell: "bash",
expectedShellCfg: &ShellConfig{
Prefix: bashUnsetPfx,
Suffix: bashUnsetSfx,
Delimiter: bashUnsetDelim,
UsageHint: generateUsageHint("minikube", "bash"),
},
},
{
description: "unset fish",
shell: "fish",
expectedShellCfg: &ShellConfig{
Prefix: fishUnsetPfx,
Suffix: fishUnsetSfx,
Delimiter: fishUnsetDelim,
UsageHint: generateUsageHint("minikube", "fish"),
},
},
{
description: "unset powershell",
shell: "powershell",
expectedShellCfg: &ShellConfig{
Prefix: psUnsetPfx,
Suffix: psUnsetSfx,
Delimiter: psUnsetDelim,
UsageHint: generateUsageHint("minikube", "powershell"),
},
},
{
description: "unset cmd",
shell: "cmd",
expectedShellCfg: &ShellConfig{
Prefix: cmdUnsetPfx,
Suffix: cmdUnsetSfx,
Delimiter: cmdUnsetDelim,
UsageHint: generateUsageHint("minikube", "cmd"),
},
},
{
description: "unset emacs",
shell: "emacs",
expectedShellCfg: &ShellConfig{
Prefix: emacsUnsetPfx,
Suffix: emacsUnsetSfx,
Delimiter: emacsUnsetDelim,
UsageHint: generateUsageHint("minikube", "emacs"),
},
},
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
defaultShellDetector = &FakeShellDetector{test.shell}
defaultNoProxyGetter = &FakeNoProxyGetter{}
actual, _ := shellCfgUnset()
if !reflect.DeepEqual(actual, test.expectedShellCfg) {
t.Errorf("Actual shell config did not match expected: \n\n actual: \n%+v \n\n expected: \n%+v \n\n", actual, test.expectedShellCfg)
}
})
}
}

View File

@ -18,7 +18,6 @@ package cluster
import (
"fmt"
"os"
"testing"
"time"
@ -338,73 +337,6 @@ func TestGetHostStatus(t *testing.T) {
checkState(state.Stopped.String())
}
func TestGetNodeDockerEnv(t *testing.T) {
RegisterMockDriver(t)
tempDir := tests.MakeTempDir()
defer os.RemoveAll(tempDir)
api := tests.NewMockAPI(t)
h, err := createHost(api, defaultMachineConfig)
if err != nil {
t.Fatalf("Error creating host: %v", err)
}
d := &tests.MockDriver{
BaseDriver: drivers.BaseDriver{
IPAddress: "127.0.0.1",
},
T: t,
}
h.Driver = d
envMap, err := GetNodeDockerEnv(api)
if err != nil {
t.Fatalf("Unexpected error getting env: %v", err)
}
dockerEnvKeys := [...]string{
constants.DockerTLSVerifyEnv,
constants.DockerHostEnv,
constants.DockerCertPathEnv,
constants.MinikubeActiveDockerdEnv,
}
for _, dockerEnvKey := range dockerEnvKeys {
if _, hasKey := envMap[dockerEnvKey]; !hasKey {
t.Fatalf("Expected envMap[\"%s\"] key to be defined", dockerEnvKey)
}
}
}
func TestGetNodeDockerEnvIPv6(t *testing.T) {
RegisterMockDriver(t)
tempDir := tests.MakeTempDir()
defer os.RemoveAll(tempDir)
api := tests.NewMockAPI(t)
h, err := createHost(api, defaultMachineConfig)
if err != nil {
t.Fatalf("Error creating host: %v", err)
}
d := &tests.MockDriver{
BaseDriver: drivers.BaseDriver{
IPAddress: "fe80::215:5dff:fe00:a903",
},
T: t,
}
h.Driver = d
envMap, err := GetNodeDockerEnv(api)
if err != nil {
t.Fatalf("Unexpected error getting env: %v", err)
}
expected := "tcp://[fe80::215:5dff:fe00:a903]:2376"
v := envMap["DOCKER_HOST"]
if v != expected {
t.Fatalf("Expected DOCKER_HOST to be defined as %s but was %s", expected, v)
}
}
func TestCreateSSHShell(t *testing.T) {
api := tests.NewMockAPI(t)

View File

@ -1,67 +0,0 @@
/*
Copyright 2020 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cluster
import (
"fmt"
"net"
"github.com/docker/machine/libmachine"
"github.com/pkg/errors"
"github.com/spf13/viper"
"k8s.io/minikube/pkg/drivers/kic"
"k8s.io/minikube/pkg/drivers/kic/oci"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/driver"
"k8s.io/minikube/pkg/minikube/localpath"
)
// GetNodeDockerEnv gets the necessary docker env variables to allow the use of docker through minikube's vm
func GetNodeDockerEnv(api libmachine.API) (map[string]string, error) {
pName := viper.GetString(config.MachineProfile)
host, err := CheckIfHostExistsAndLoad(api, pName)
if err != nil {
return nil, errors.Wrap(err, "Error checking that api exists and loading it")
}
ip := kic.DefaultBindIPV4
if !driver.IsKIC(host.Driver.DriverName()) { // kic externally accessible ip is different that node ip
ip, err = host.Driver.GetIP()
if err != nil {
return nil, errors.Wrap(err, "Error getting ip from host")
}
}
tcpPrefix := "tcp://"
port := constants.DockerDaemonPort
if driver.IsKIC(host.Driver.DriverName()) { // for kic we need to find out what port docker allocated during creation
port, err = oci.HostPortBinding(host.Driver.DriverName(), pName, constants.DockerDaemonPort)
if err != nil {
return nil, errors.Wrapf(err, "get hostbind port for %d", constants.DockerDaemonPort)
}
}
envMap := map[string]string{
constants.DockerTLSVerifyEnv: "1",
constants.DockerHostEnv: tcpPrefix + net.JoinHostPort(ip, fmt.Sprint(port)),
constants.DockerCertPathEnv: localpath.MakeMiniPath("certs"),
constants.MinikubeActiveDockerdEnv: pName,
}
return envMap, nil
}