Fix docker-env command

pull/9510/head
Ilya Zuyev 2020-10-20 23:10:08 -07:00
parent d384343c39
commit 85d45be207
8 changed files with 168 additions and 36 deletions

View File

@ -30,6 +30,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/klog/v2" "k8s.io/klog/v2"
"k8s.io/minikube/pkg/drivers/kic/oci" "k8s.io/minikube/pkg/drivers/kic/oci"
"k8s.io/minikube/pkg/minikube/command" "k8s.io/minikube/pkg/minikube/command"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
@ -43,7 +44,31 @@ import (
"k8s.io/minikube/pkg/minikube/sysinit" "k8s.io/minikube/pkg/minikube/sysinit"
) )
var dockerEnvTmpl = 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) var dockerSetEnvTmpl = fmt.Sprintf(
"{{ .Prefix }}%s{{ .Delimiter }}{{ .DockerTLSVerify }}{{ .Suffix }}"+
"{{ .Prefix }}%s{{ .Delimiter }}{{ .DockerHost }}{{ .Suffix }}"+
"{{ .Prefix }}%s{{ .Delimiter }}{{ .DockerCertPath }}{{ .Suffix }}"+
"{{ if .ExistingDockerTLSVerify }}"+
"{{ .Prefix }}%s{{ .Delimiter }}{{ .ExistingDockerTLSVerify }}{{ .Suffix }}"+
"{{ end }}"+
"{{ if .ExistingDockerHost }}"+
"{{ .Prefix }}%s{{ .Delimiter }}{{ .ExistingDockerHost }}{{ .Suffix }}"+
"{{ end }}"+
"{{ if .ExistingDockerCertPath }}"+
"{{ .Prefix }}%s{{ .Delimiter }}{{ .ExistingDockerCertPath }}{{ .Suffix }}"+
"{{ end }}"+
"{{ .Prefix }}%s{{ .Delimiter }}{{ .MinikubeDockerdProfile }}{{ .Suffix }}"+
"{{ if .NoProxyVar }}"+
"{{ .Prefix }}{{ .NoProxyVar }}{{ .Delimiter }}{{ .NoProxyValue }}{{ .Suffix }}"+
"{{ end }}"+
"{{ .UsageHint }}",
constants.DockerTLSVerifyEnv,
constants.DockerHostEnv,
constants.DockerCertPathEnv,
constants.ExistingDockerTLSVerifyEnv,
constants.ExistingDockerHostEnv,
constants.ExistingDockerCertPathEnv,
constants.MinikubeActiveDockerdEnv)
// DockerShellConfig represents the shell config for Docker // DockerShellConfig represents the shell config for Docker
type DockerShellConfig struct { type DockerShellConfig struct {
@ -54,6 +79,10 @@ type DockerShellConfig struct {
MinikubeDockerdProfile string MinikubeDockerdProfile string
NoProxyVar string NoProxyVar string
NoProxyValue string NoProxyValue string
ExistingDockerCertPath string
ExistingDockerHost string
ExistingDockerTLSVerify string
} }
var ( var (
@ -81,6 +110,11 @@ func dockerShellCfgSet(ec DockerEnvConfig, envMap map[string]string) *DockerShel
s.DockerCertPath = envMap[constants.DockerCertPathEnv] s.DockerCertPath = envMap[constants.DockerCertPathEnv]
s.DockerHost = envMap[constants.DockerHostEnv] s.DockerHost = envMap[constants.DockerHostEnv]
s.DockerTLSVerify = envMap[constants.DockerTLSVerifyEnv] s.DockerTLSVerify = envMap[constants.DockerTLSVerifyEnv]
s.ExistingDockerCertPath = envMap[constants.ExistingDockerCertPathEnv]
s.ExistingDockerHost = envMap[constants.ExistingDockerHostEnv]
s.ExistingDockerTLSVerify = envMap[constants.ExistingDockerTLSVerifyEnv]
s.MinikubeDockerdProfile = envMap[constants.MinikubeActiveDockerdEnv] s.MinikubeDockerdProfile = envMap[constants.MinikubeActiveDockerdEnv]
if ec.noProxy { if ec.noProxy {
@ -228,7 +262,7 @@ type DockerEnvConfig struct {
// dockerSetScript writes out a shell-compatible 'docker-env' script // dockerSetScript writes out a shell-compatible 'docker-env' script
func dockerSetScript(ec DockerEnvConfig, w io.Writer) error { func dockerSetScript(ec DockerEnvConfig, w io.Writer) error {
envVars := dockerEnvVars(ec) envVars := dockerEnvVars(ec)
return shell.SetScript(ec.EnvConfig, w, dockerEnvTmpl, dockerShellCfgSet(ec, envVars)) return shell.SetScript(ec.EnvConfig, w, dockerSetEnvTmpl, dockerShellCfgSet(ec, envVars))
} }
// dockerSetScript writes out a shell-compatible 'docker-env unset' script // dockerSetScript writes out a shell-compatible 'docker-env unset' script
@ -246,7 +280,6 @@ func dockerUnsetScript(ec DockerEnvConfig, w io.Writer) error {
vars = append(vars, k) vars = append(vars, k)
} }
} }
return shell.UnsetScript(ec.EnvConfig, w, vars) return shell.UnsetScript(ec.EnvConfig, w, vars)
} }
@ -257,14 +290,21 @@ func dockerURL(ip string, port int) string {
// dockerEnvVars gets the necessary docker env variables to allow the use of minikube's docker daemon // dockerEnvVars gets the necessary docker env variables to allow the use of minikube's docker daemon
func dockerEnvVars(ec DockerEnvConfig) map[string]string { func dockerEnvVars(ec DockerEnvConfig) map[string]string {
env := map[string]string{ rt := map[string]string{
constants.DockerTLSVerifyEnv: "1", constants.DockerTLSVerifyEnv: "1",
constants.DockerHostEnv: dockerURL(ec.hostIP, ec.port), constants.DockerHostEnv: dockerURL(ec.hostIP, ec.port),
constants.DockerCertPathEnv: ec.certsDir, constants.DockerCertPathEnv: ec.certsDir,
constants.MinikubeActiveDockerdEnv: ec.profile, constants.MinikubeActiveDockerdEnv: ec.profile,
} }
if os.Getenv(constants.MinikubeActiveDockerdEnv) == "" {
return env for _, env := range constants.DockerDaemonEnvs {
if v := oci.InitialEnv(env); v != "" {
key := constants.MinikubeExistingPrefix + env
rt[key] = v
}
}
}
return rt
} }
// dockerEnvVarsList gets the necessary docker env variables to allow the use of minikube's docker daemon to be used in a exec.Command // dockerEnvVarsList gets the necessary docker env variables to allow the use of minikube's docker daemon to be used in a exec.Command

View File

@ -95,10 +95,11 @@ func (d *Driver) Create() error {
} }
// control plane specific options // control plane specific options
params.PortMappings = append(params.PortMappings, oci.PortMapping{ params.PortMappings = append(params.PortMappings,
ListenAddress: oci.DefaultBindIPV4, oci.PortMapping{
ContainerPort: int32(params.APIServerPort), ListenAddress: oci.DefaultBindIPV4,
}, ContainerPort: int32(params.APIServerPort),
},
oci.PortMapping{ oci.PortMapping{
ListenAddress: oci.DefaultBindIPV4, ListenAddress: oci.DefaultBindIPV4,
ContainerPort: constants.SSHPort, ContainerPort: constants.SSHPort,

View File

@ -0,0 +1,47 @@
/*
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 oci
import (
"os"
"k8s.io/minikube/pkg/minikube/constants"
)
var initialEnvs = make(map[string]string)
func init() {
for _, env := range constants.DockerDaemonEnvs {
if v, set := os.LookupEnv(env); set {
initialEnvs[env] = v
}
exEnv := constants.MinikubeExistingPrefix + env
if v, set := os.LookupEnv(exEnv); set {
initialEnvs[exEnv] = v
}
}
}
// InitialEnv returns the value of the environment variable env before any environment changes made by minikube
func InitialEnv(env string) string {
return initialEnvs[env]
}
// LookupInitialEnv returns the value of the environment variable env before any environment changes made by minikube
func LookupInitialEnv(env string) (string, bool) {
v, set := initialEnvs[env]
return v, set
}

View File

@ -523,11 +523,10 @@ func PointToHostDockerDaemon() error {
if p := os.Getenv(constants.MinikubeActiveDockerdEnv); p != "" { if p := os.Getenv(constants.MinikubeActiveDockerdEnv); p != "" {
klog.Infof("shell is pointing to dockerd inside minikube. will unset to use host") klog.Infof("shell is pointing to dockerd inside minikube. will unset to use host")
} for _, e := range constants.DockerDaemonEnvs {
if err := resetEnv(e); err != nil {
for _, e := range constants.DockerDaemonEnvs { return err
if err := resetEnv(e); err != nil { }
return err
} }
} }
@ -542,7 +541,6 @@ func resetEnv(key string) error {
} }
return nil return nil
} }
if err := os.Setenv(key, v); err != nil { if err := os.Setenv(key, v); err != nil {
return errors.Wrapf(err, "resetting %s env", key) return errors.Wrapf(err, "resetting %s env", key)
} }

View File

@ -25,6 +25,7 @@ func TestPointToHostDockerDaemonEmpty(t *testing.T) {
_ = os.Setenv("DOCKER_HOST", "foo_host") _ = os.Setenv("DOCKER_HOST", "foo_host")
_ = os.Setenv("DOCKER_CERT_PATH", "foo_cert_path") _ = os.Setenv("DOCKER_CERT_PATH", "foo_cert_path")
_ = os.Setenv("DOCKER_TLS_VERIFY", "foo_tls_verify") _ = os.Setenv("DOCKER_TLS_VERIFY", "foo_tls_verify")
_ = os.Setenv("MINIKUBE_ACTIVE_DOCKERD", "minikube")
_ = os.Unsetenv("MINIKUBE_EXISTING_DOCKER_HOST") _ = os.Unsetenv("MINIKUBE_EXISTING_DOCKER_HOST")
_ = os.Unsetenv("MINIKUBE_EXISTING_DOCKER_CERT_PATH") _ = os.Unsetenv("MINIKUBE_EXISTING_DOCKER_CERT_PATH")

View File

@ -75,8 +75,16 @@ const (
MinikubeForceSystemdEnv = "MINIKUBE_FORCE_SYSTEMD" MinikubeForceSystemdEnv = "MINIKUBE_FORCE_SYSTEMD"
// TestDiskUsedEnv is used in integration tests for insufficient storage with 'minikube status' // TestDiskUsedEnv is used in integration tests for insufficient storage with 'minikube status'
TestDiskUsedEnv = "MINIKUBE_TEST_STORAGE_CAPACITY" TestDiskUsedEnv = "MINIKUBE_TEST_STORAGE_CAPACITY"
// MinikubeExistingPrefix is used to save the original environment when executing docker-env // MinikubeExistingPrefix is used to save the original environment when executing docker-env
MinikubeExistingPrefix = "MINIKUBE_EXISTING_" MinikubeExistingPrefix = "MINIKUBE_EXISTING_"
// ExistingDockerHostEnv is used to save original docker environment
ExistingDockerHostEnv = MinikubeExistingPrefix + "DOCKER_HOST"
// ExistingDockerCertPathEnv is used to save original docker environment
ExistingDockerCertPathEnv = MinikubeExistingPrefix + "DOCKER_CERT_PATH"
// ExistingDockerTLSVerifyEnv is used to save original docker environment
ExistingDockerTLSVerifyEnv = MinikubeExistingPrefix + "DOCKER_TLS_VERIFY"
) )
var ( var (
@ -92,6 +100,9 @@ var (
// DockerDaemonEnvs is list of docker-daemon related environment variables. // DockerDaemonEnvs is list of docker-daemon related environment variables.
DockerDaemonEnvs = [3]string{DockerHostEnv, DockerTLSVerifyEnv, DockerCertPathEnv} DockerDaemonEnvs = [3]string{DockerHostEnv, DockerTLSVerifyEnv, DockerCertPathEnv}
// ExistingDockerDaemonEnvs is list of docker-daemon related environment variables.
ExistingDockerDaemonEnvs = [3]string{ExistingDockerHostEnv, ExistingDockerTLSVerifyEnv, ExistingDockerCertPathEnv}
// PodmanRemoteEnvs is list of podman-remote related environment variables. // PodmanRemoteEnvs is list of podman-remote related environment variables.
PodmanRemoteEnvs = [1]string{PodmanVarlinkBridgeEnv} PodmanRemoteEnvs = [1]string{PodmanVarlinkBridgeEnv}

View File

@ -24,12 +24,21 @@ import (
"io" "io"
"os" "os"
"runtime" "runtime"
"strings"
"text/template" "text/template"
"github.com/docker/machine/libmachine/shell" "github.com/docker/machine/libmachine/shell"
"k8s.io/minikube/pkg/minikube/constants"
) )
var unsetEnvTmpl = "{{ $root := .}}" +
"{{ range .Unset }}" +
"{{ $root.UnsetPrefix }}{{ . }}{{ $root.UnsetDelimiter }}{{ $root.UnsetSuffix }}" +
"{{ end }}" +
"{{ range .Set }}" +
"{{ $root.SetPrefix }}{{ .Env }}{{ $root.SetDelimiter }}{{ .Value }}{{ $root.SetSuffix }}" +
"{{ end }}"
// Config represents the shell config // Config represents the shell config
type Config struct { type Config struct {
Prefix string Prefix string
@ -107,7 +116,7 @@ REM @FOR /f "tokens=*" %%i IN ('%s') DO @%%i
suffix: "\"\n", suffix: "\"\n",
delimiter: "=\"", delimiter: "=\"",
unsetPrefix: "unset ", unsetPrefix: "unset ",
unsetSuffix: "\n", unsetSuffix: ";\n",
unsetDelimiter: "", unsetDelimiter: "",
usageHint: func(s ...interface{}) string { usageHint: func(s ...interface{}) string {
return fmt.Sprintf(` return fmt.Sprintf(`
@ -181,24 +190,46 @@ func SetScript(ec EnvConfig, w io.Writer, envTmpl string, data interface{}) erro
return tmpl.Execute(w, data) return tmpl.Execute(w, data)
} }
type unsetConfigItem struct {
Env, Value string
}
type unsetConfig struct {
Set []unsetConfigItem
Unset []string
SetPrefix string
SetDelimiter string
SetSuffix string
UnsetPrefix string
UnsetDelimiter string
UnsetSuffix string
}
// UnsetScript writes out a shell-compatible unset script // UnsetScript writes out a shell-compatible unset script
func UnsetScript(ec EnvConfig, w io.Writer, vars []string) error { func UnsetScript(ec EnvConfig, w io.Writer, vars []string) error {
var sb strings.Builder
shellCfg := ec.getShell() shellCfg := ec.getShell()
pfx, sfx, delim := shellCfg.unsetPrefix, shellCfg.unsetSuffix, shellCfg.unsetDelimiter cfg := unsetConfig{
switch ec.Shell { SetPrefix: shellCfg.prefix,
case "cmd", "emacs", "fish": SetDelimiter: shellCfg.delimiter,
break SetSuffix: shellCfg.suffix,
case "powershell": UnsetPrefix: shellCfg.unsetPrefix,
vars = []string{strings.Join(vars, " Env:\\\\")} UnsetDelimiter: shellCfg.unsetDelimiter,
default: UnsetSuffix: shellCfg.unsetSuffix,
vars = []string{strings.Join(vars, " ")}
} }
for _, v := range vars { var tempUnset []string
if _, err := sb.WriteString(fmt.Sprintf("%s%s%s%s", pfx, v, delim, sfx)); err != nil { for _, env := range vars {
return err exEnv := constants.MinikubeExistingPrefix + env
if v := os.Getenv(exEnv); v == "" {
cfg.Unset = append(cfg.Unset, env)
} else {
cfg.Set = append(cfg.Set, unsetConfigItem{
Env: env,
Value: v,
})
tempUnset = append(tempUnset, exEnv)
} }
} }
_, err := w.Write([]byte(sb.String())) cfg.Unset = append(cfg.Unset, tempUnset...)
return err
tmpl := template.Must(template.New("unsetEnv").Parse(unsetEnvTmpl))
return tmpl.Execute(w, &cfg)
} }

View File

@ -87,16 +87,19 @@ func TestUnsetScript(t *testing.T) {
ec EnvConfig ec EnvConfig
expected string expected string
}{ }{
{[]string{"baz", "bar"}, EnvConfig{""}, `unset baz bar`}, {[]string{"baz", "bar"}, EnvConfig{""}, `unset baz;
{[]string{"baz", "bar"}, EnvConfig{"bash"}, `unset baz bar`}, unset bar;`},
{[]string{"baz", "bar"}, EnvConfig{"powershell"}, `Remove-Item Env:\\baz Env:\\bar`}, {[]string{"baz", "bar"}, EnvConfig{"bash"}, `unset baz;
unset bar;`},
{[]string{"baz", "bar"}, EnvConfig{"powershell"}, `Remove-Item Env:\\baz
Remove-Item Env:\\bar`},
{[]string{"baz", "bar"}, EnvConfig{"cmd"}, `SET baz= {[]string{"baz", "bar"}, EnvConfig{"cmd"}, `SET baz=
SET bar=`}, SET bar=`},
{[]string{"baz", "bar"}, EnvConfig{"fish"}, `set -e baz; {[]string{"baz", "bar"}, EnvConfig{"fish"}, `set -e baz;
set -e bar;`}, set -e bar;`},
{[]string{"baz", "bar"}, EnvConfig{"emacs"}, `(setenv "baz" nil) {[]string{"baz", "bar"}, EnvConfig{"emacs"}, `(setenv "baz" nil)
(setenv "bar" nil)`}, (setenv "bar" nil)`},
{[]string{"baz", "bar"}, EnvConfig{"none"}, `baz bar`}, {[]string{"baz", "bar"}, EnvConfig{"none"}, "baz\nbar"},
} }
for _, tc := range testCases { for _, tc := range testCases {
tc := tc tc := tc