From 7ebef128f3e364c885f9642a8d9f7c912141278f Mon Sep 17 00:00:00 2001 From: xichengliudui <1693291525@qq.com> Date: Thu, 26 Sep 2019 18:20:04 +0800 Subject: [PATCH 01/78] Remove the redundant code in util.go update pull request --- pkg/util/utils.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/util/utils.go b/pkg/util/utils.go index c549ca4ebe..ec2d8f6faf 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -34,13 +34,13 @@ import ( "k8s.io/minikube/pkg/minikube/out" ) -// ErrPrefix notes an error -const ErrPrefix = "! " - -// OutPrefix notes output -const OutPrefix = "> " - const ( + // ErrPrefix notes an error + ErrPrefix = "! " + + // OutPrefix notes output + OutPrefix = "> " + downloadURL = "https://storage.googleapis.com/minikube/releases/%s/minikube-%s-amd64%s" ) From 6ef1ee3e17677733d9db19cf35c303c64bae59d6 Mon Sep 17 00:00:00 2001 From: Marcin Niemira Date: Tue, 1 Oct 2019 23:45:22 +1000 Subject: [PATCH 02/78] improve test coverage in machine --- pkg/minikube/machine/cache_binaries_test.go | 189 ++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 pkg/minikube/machine/cache_binaries_test.go diff --git a/pkg/minikube/machine/cache_binaries_test.go b/pkg/minikube/machine/cache_binaries_test.go new file mode 100644 index 0000000000..484ce95251 --- /dev/null +++ b/pkg/minikube/machine/cache_binaries_test.go @@ -0,0 +1,189 @@ +package machine + +import ( + "fmt" + "io/ioutil" + "os" + "runtime" + "testing" + + "k8s.io/minikube/pkg/minikube/assets" + "k8s.io/minikube/pkg/minikube/bootstrapper" + "k8s.io/minikube/pkg/minikube/command" +) + +type copyFailRunner struct { + command.Runner +} + +func (copyFailRunner) Copy(a assets.CopyableFile) error { + return fmt.Errorf("test error during copy file") +} + +func TestCopyBinary(t *testing.T) { + + fakeCommandRunnerCopyFail := func() command.Runner { + r := command.NewFakeCommandRunner() + return copyFailRunner{r} + } + + var tc = []struct { + lastUpdateCheckFilePath string + src, dst, desc string + err bool + runner command.Runner + }{ + { + desc: "not existing src", + dst: "/tmp/testCopyBinary1", + src: "/tmp/testCopyBinary2", + err: true, + runner: command.NewFakeCommandRunner(), + }, + { + desc: "src /etc/hosts", + dst: "/tmp/testCopyBinary1", + src: "/etc/hosts", + err: false, + runner: command.NewFakeCommandRunner(), + }, + { + desc: "existing src, dst without permissions", + dst: "/etc/passwd", + src: "/etc/hosts", + err: true, + runner: fakeCommandRunnerCopyFail(), + }, + } + for _, test := range tc { + t.Run(test.desc, func(t *testing.T) { + err := CopyBinary(test.runner, test.src, test.dst) + if err != nil && !test.err { + t.Fatalf("Error %v expected but not occured", err) + } + if err == nil && test.err { + t.Fatal("Unexpected error") + } + }) + } +} + +func TestCacheBinariesForBootstrapper(t *testing.T) { + var tc = []struct { + version, clusterBootstrapper string + err bool + }{ + { + version: "v1.16.0", + clusterBootstrapper: bootstrapper.BootstrapperTypeKubeadm, + }, + { + version: "invalid version", + clusterBootstrapper: bootstrapper.BootstrapperTypeKubeadm, + err: true, + }, + } + for _, test := range tc { + t.Run(test.version, func(t *testing.T) { + err := CacheBinariesForBootstrapper(test.version, test.clusterBootstrapper) + if err != nil && !test.err { + t.Fatalf("Got unexpected error %v", err) + } + if err == nil && test.err { + t.Fatalf("Expected error but got %v", err) + } + }) + } +} +func TestCacheBinary(t *testing.T) { + oldMinikubeHome := os.Getenv("MINIKUBE_HOME") + defer os.Setenv("MINIKUBE_HOME", oldMinikubeHome) + + minikubeHome, err := ioutil.TempDir("/tmp", "") + if err != nil { + t.Fatalf("error during creating tmp dir: %v", err) + } + defer os.RemoveAll(minikubeHome) + + var tc = []struct { + desc, version, osName, archName string + minikubeHome, binary, description string + err bool + }{ + { + desc: "ok kubeadm", + version: "v1.16.0", + osName: runtime.GOOS, + archName: runtime.GOARCH, + binary: "kubeadm", + err: false, + minikubeHome: minikubeHome, + }, + { + desc: "minikube home is dev/null", + version: "v1.16.0", + osName: runtime.GOOS, + archName: "arm", + binary: "kubectl", + err: true, + minikubeHome: "/dev/null", + }, + { + desc: "minikube home in etc and arm runtime", + version: "v1.16.0", + osName: runtime.GOOS, + archName: "arm", + binary: "kubectl", + err: true, + minikubeHome: "/etc", + }, + { + desc: "minikube home in etc", + version: "v1.16.0", + osName: runtime.GOOS, + archName: runtime.GOARCH, + binary: "kubectl", + err: true, + minikubeHome: "/etc", + }, + { + desc: "binary foo", + version: "v1.16.0", + osName: runtime.GOOS, + archName: runtime.GOARCH, + binary: "foo", + err: true, + minikubeHome: minikubeHome, + }, + { + desc: "version 9000", + version: "v9000", + osName: runtime.GOOS, + archName: runtime.GOARCH, + binary: "foo", + err: true, + minikubeHome: minikubeHome, + }, + { + desc: "bad os", + version: "v1.16.0", + osName: "no-such-os", + archName: runtime.GOARCH, + binary: "kubectl", + err: true, + minikubeHome: minikubeHome, + }, + } + for _, test := range tc { + t.Run(test.desc, func(t *testing.T) { + os.Setenv("MINIKUBE_HOME", test.minikubeHome) + _, err := CacheBinary(test.binary, test.version, test.osName, test.archName) + if err != nil && !test.err { + t.Fatalf("Got unexpected error %v", err) + } + if err == nil && test.err { + t.Fatalf("Expected error but got %v", err) + } + }) + } +} From e3a84f5f60a8754562918177646f6c41f7c7b8de Mon Sep 17 00:00:00 2001 From: Marcin Niemira Date: Tue, 1 Oct 2019 23:46:07 +1000 Subject: [PATCH 03/78] add boilerplate --- pkg/minikube/machine/cache_binaries_test.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pkg/minikube/machine/cache_binaries_test.go b/pkg/minikube/machine/cache_binaries_test.go index 484ce95251..03d5752b1c 100644 --- a/pkg/minikube/machine/cache_binaries_test.go +++ b/pkg/minikube/machine/cache_binaries_test.go @@ -1,3 +1,19 @@ +/* +Copyright 2019 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 machine import ( From 8d95d98348e57e63c197a3e5f3b295a9bf65f3d7 Mon Sep 17 00:00:00 2001 From: Marcin Niemira Date: Tue, 1 Oct 2019 23:49:49 +1000 Subject: [PATCH 04/78] self review fixes --- pkg/minikube/machine/cache_binaries_test.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/pkg/minikube/machine/cache_binaries_test.go b/pkg/minikube/machine/cache_binaries_test.go index 03d5752b1c..767c1136b3 100644 --- a/pkg/minikube/machine/cache_binaries_test.go +++ b/pkg/minikube/machine/cache_binaries_test.go @@ -36,13 +36,11 @@ func (copyFailRunner) Copy(a assets.CopyableFile) error { return fmt.Errorf("test error during copy file") } +func newFakeCommandRunnerCopyFail() command.Runner { + return copyFailRunner{command.NewFakeCommandRunner()} +} + func TestCopyBinary(t *testing.T) { - - fakeCommandRunnerCopyFail := func() command.Runner { - r := command.NewFakeCommandRunner() - return copyFailRunner{r} - } - var tc = []struct { lastUpdateCheckFilePath string src, dst, desc string @@ -68,7 +66,7 @@ func TestCopyBinary(t *testing.T) { dst: "/etc/passwd", src: "/etc/hosts", err: true, - runner: fakeCommandRunnerCopyFail(), + runner: newFakeCommandRunnerCopyFail(), }, } for _, test := range tc { From a99d6e934598f8fd540390791c2f7c43731cd565 Mon Sep 17 00:00:00 2001 From: Marcin Niemira Date: Tue, 1 Oct 2019 23:54:25 +1000 Subject: [PATCH 05/78] msg improvement --- pkg/minikube/machine/cache_binaries_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/minikube/machine/cache_binaries_test.go b/pkg/minikube/machine/cache_binaries_test.go index 767c1136b3..a252480de8 100644 --- a/pkg/minikube/machine/cache_binaries_test.go +++ b/pkg/minikube/machine/cache_binaries_test.go @@ -62,7 +62,7 @@ func TestCopyBinary(t *testing.T) { runner: command.NewFakeCommandRunner(), }, { - desc: "existing src, dst without permissions", + desc: "existing src, copy fail", dst: "/etc/passwd", src: "/etc/hosts", err: true, From f0eb90d941a156ef66335384094a20e559a7c6c9 Mon Sep 17 00:00:00 2001 From: Marcin Niemira Date: Wed, 2 Oct 2019 17:52:31 +1000 Subject: [PATCH 06/78] typofix --- pkg/minikube/machine/cache_binaries_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/minikube/machine/cache_binaries_test.go b/pkg/minikube/machine/cache_binaries_test.go index a252480de8..72da130aff 100644 --- a/pkg/minikube/machine/cache_binaries_test.go +++ b/pkg/minikube/machine/cache_binaries_test.go @@ -73,7 +73,7 @@ func TestCopyBinary(t *testing.T) { t.Run(test.desc, func(t *testing.T) { err := CopyBinary(test.runner, test.src, test.dst) if err != nil && !test.err { - t.Fatalf("Error %v expected but not occured", err) + t.Fatalf("Error %v expected but not occurred", err) } if err == nil && test.err { t.Fatal("Unexpected error") From eff9be260f926073d9591be3283509e147a8f376 Mon Sep 17 00:00:00 2001 From: Marcin Niemira Date: Wed, 2 Oct 2019 18:30:08 +1000 Subject: [PATCH 07/78] remove unix specific files from tests --- pkg/minikube/machine/cache_binaries_test.go | 26 +++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/pkg/minikube/machine/cache_binaries_test.go b/pkg/minikube/machine/cache_binaries_test.go index 72da130aff..1f2fd4daad 100644 --- a/pkg/minikube/machine/cache_binaries_test.go +++ b/pkg/minikube/machine/cache_binaries_test.go @@ -118,7 +118,19 @@ func TestCacheBinary(t *testing.T) { t.Fatalf("error during creating tmp dir: %v", err) } defer os.RemoveAll(minikubeHome) - + noWritePermDir, err := ioutil.TempDir("/tmp", "") + if err != nil { + t.Fatalf("error during creating tmp dir: %v", err) + } + defer os.RemoveAll(noWritePermDir) + err = os.Chmod(noWritePermDir, 0000) + if err != nil { + t.Fatalf("error (%v) during changing permissions of dir %v", err, noWritePermDir) + } + noPermsDir := "/etc" + if runtime.GOOS == "windows" { + noPermsDir = "C:\\Windows\\System32" + } var tc = []struct { desc, version, osName, archName string minikubeHome, binary, description string @@ -134,31 +146,31 @@ func TestCacheBinary(t *testing.T) { minikubeHome: minikubeHome, }, { - desc: "minikube home is dev/null", + desc: "minikube home is pointing to dir without perms", version: "v1.16.0", osName: runtime.GOOS, archName: "arm", binary: "kubectl", err: true, - minikubeHome: "/dev/null", + minikubeHome: noPermsDir, }, { - desc: "minikube home in etc and arm runtime", + desc: "minikube home in dir without perms and arm runtime", version: "v1.16.0", osName: runtime.GOOS, archName: "arm", binary: "kubectl", err: true, - minikubeHome: "/etc", + minikubeHome: noWritePermDir, }, { - desc: "minikube home in etc", + desc: "minikube home in dir without perms", version: "v1.16.0", osName: runtime.GOOS, archName: runtime.GOARCH, binary: "kubectl", err: true, - minikubeHome: "/etc", + minikubeHome: noWritePermDir, }, { desc: "binary foo", From e73c10495572a4c9e99adb1da7721ea12b8596da Mon Sep 17 00:00:00 2001 From: Marcin Niemira Date: Thu, 3 Oct 2019 15:30:31 +1000 Subject: [PATCH 08/78] add requested comment --- pkg/minikube/machine/cache_binaries_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/minikube/machine/cache_binaries_test.go b/pkg/minikube/machine/cache_binaries_test.go index 1f2fd4daad..b522de6976 100644 --- a/pkg/minikube/machine/cache_binaries_test.go +++ b/pkg/minikube/machine/cache_binaries_test.go @@ -127,6 +127,8 @@ func TestCacheBinary(t *testing.T) { if err != nil { t.Fatalf("error (%v) during changing permissions of dir %v", err, noWritePermDir) } + + // noPermsDir is directory owned by root. Regular user is not able to write to it. noPermsDir := "/etc" if runtime.GOOS == "windows" { noPermsDir = "C:\\Windows\\System32" From 0945ed881bcdbe05f02290f9001c4655a114768c Mon Sep 17 00:00:00 2001 From: Pranav Jituri Date: Sun, 6 Oct 2019 16:17:30 +0530 Subject: [PATCH 09/78] Added flags to purge configuration --- cmd/minikube/cmd/delete.go | 54 ++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/cmd/minikube/cmd/delete.go b/cmd/minikube/cmd/delete.go index 9125650c00..99e94e7722 100644 --- a/cmd/minikube/cmd/delete.go +++ b/cmd/minikube/cmd/delete.go @@ -17,20 +17,16 @@ limitations under the License. package cmd import ( + "bufio" "fmt" - "io/ioutil" - "os" - "path/filepath" - "strconv" - + "github.com/docker/machine/libmachine" "github.com/docker/machine/libmachine/mcnerror" "github.com/golang/glog" - ps "github.com/mitchellh/go-ps" + "github.com/mitchellh/go-ps" "github.com/pkg/errors" - - "github.com/docker/machine/libmachine" "github.com/spf13/cobra" "github.com/spf13/viper" + "io/ioutil" cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config" "k8s.io/minikube/pkg/minikube/cluster" pkg_config "k8s.io/minikube/pkg/minikube/config" @@ -40,6 +36,15 @@ import ( "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/out" + "os" + "path/filepath" + "strconv" + "strings" +) + +const ( + purge = "purge" + noPrompt = "no-prompt" ) // deleteCmd represents the delete command @@ -51,6 +56,15 @@ associated files.`, Run: runDelete, } +func init() { + deleteCmd.Flags().Bool(purge,false,"Set this flag to delete the '.minikube' folder from your user directory. This will prompt for confirmation.") + deleteCmd.Flags().Bool(noPrompt, false,"Set this flag so that there are no prompts.") + + if err := viper.BindPFlags(deleteCmd.Flags()); err != nil { + exit.WithError("unable to bind flags", err) + } +} + // runDelete handles the executes the flow of "minikube delete" func runDelete(cmd *cobra.Command, args []string) { if len(args) > 0 { @@ -107,6 +121,30 @@ func runDelete(cmd *cobra.Command, args []string) { if err := cmdcfg.Unset(pkg_config.MachineProfile); err != nil { exit.WithError("unset minikube profile", err) } + + // Delete the .minikube folder if the flags are set + if viper.GetBool(purge) { + glog.Infof("Purging the '.minikube' directory located at %s", localpath.MiniPath()) + + if viper.GetBool(noPrompt) { + glog.Infof("Will not prompt for deletion.") + } else { + out.T(out.Check,"Are you sure you want to delete the directory located at {{.minikubePath}}? This will delete all your configuration data related to minikube. (Y/N)", out.V{"minikubePath":localpath.MiniPath()}) + userInput := bufio.NewScanner(os.Stdin) + userInput.Scan() + var choice = userInput.Text() + if strings.ToLower(choice) != "y" { + out.T(out.Meh,"Not deleting minikube directory located at {{.minikubePath}}",out.V{"minikubePath":localpath.MiniPath()}) + return + } + } + if err := os.RemoveAll(localpath.MiniPath()); err != nil { + exit.WithError("unable to delete minikube config folder", err) + } + out.T(out.Crushed,"Deleted the {{.minikubePath}} folder successfully!", out.V{"minikubePath":localpath.MiniPath()}) + } else { + out.T(out.Meh,"Not deleting minikube directory located at {{.minikubePath}}",out.V{"minikubePath":localpath.MiniPath()}) + } } func uninstallKubernetes(api libmachine.API, kc pkg_config.KubernetesConfig, bsName string) { From cb5055ef192082d0bbb72da163264ba3b017d959 Mon Sep 17 00:00:00 2001 From: Pranav Jituri Date: Sun, 6 Oct 2019 16:32:24 +0530 Subject: [PATCH 10/78] Fixed linting error --- cmd/minikube/cmd/delete.go | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/cmd/minikube/cmd/delete.go b/cmd/minikube/cmd/delete.go index 99e94e7722..d7b3fdee2c 100644 --- a/cmd/minikube/cmd/delete.go +++ b/cmd/minikube/cmd/delete.go @@ -19,6 +19,12 @@ package cmd import ( "bufio" "fmt" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" + "github.com/docker/machine/libmachine" "github.com/docker/machine/libmachine/mcnerror" "github.com/golang/glog" @@ -26,7 +32,6 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" - "io/ioutil" cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config" "k8s.io/minikube/pkg/minikube/cluster" pkg_config "k8s.io/minikube/pkg/minikube/config" @@ -36,15 +41,11 @@ import ( "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/out" - "os" - "path/filepath" - "strconv" - "strings" ) const ( - purge = "purge" - noPrompt = "no-prompt" + purge = "purge" + noPrompt = "no-prompt" ) // deleteCmd represents the delete command @@ -57,8 +58,8 @@ associated files.`, } func init() { - deleteCmd.Flags().Bool(purge,false,"Set this flag to delete the '.minikube' folder from your user directory. This will prompt for confirmation.") - deleteCmd.Flags().Bool(noPrompt, false,"Set this flag so that there are no prompts.") + deleteCmd.Flags().Bool(purge, false, "Set this flag to delete the '.minikube' folder from your user directory. This will prompt for confirmation.") + deleteCmd.Flags().Bool(noPrompt, false, "Set this flag so that there are no prompts.") if err := viper.BindPFlags(deleteCmd.Flags()); err != nil { exit.WithError("unable to bind flags", err) @@ -129,21 +130,21 @@ func runDelete(cmd *cobra.Command, args []string) { if viper.GetBool(noPrompt) { glog.Infof("Will not prompt for deletion.") } else { - out.T(out.Check,"Are you sure you want to delete the directory located at {{.minikubePath}}? This will delete all your configuration data related to minikube. (Y/N)", out.V{"minikubePath":localpath.MiniPath()}) + out.T(out.Check, "Are you sure you want to delete the directory located at {{.minikubePath}}? This will delete all your configuration data related to minikube. (Y/N)", out.V{"minikubePath": localpath.MiniPath()}) userInput := bufio.NewScanner(os.Stdin) userInput.Scan() var choice = userInput.Text() if strings.ToLower(choice) != "y" { - out.T(out.Meh,"Not deleting minikube directory located at {{.minikubePath}}",out.V{"minikubePath":localpath.MiniPath()}) + out.T(out.Meh, "Not deleting minikube directory located at {{.minikubePath}}", out.V{"minikubePath": localpath.MiniPath()}) return } } if err := os.RemoveAll(localpath.MiniPath()); err != nil { exit.WithError("unable to delete minikube config folder", err) } - out.T(out.Crushed,"Deleted the {{.minikubePath}} folder successfully!", out.V{"minikubePath":localpath.MiniPath()}) + out.T(out.Crushed, "Deleted the {{.minikubePath}} folder successfully!", out.V{"minikubePath": localpath.MiniPath()}) } else { - out.T(out.Meh,"Not deleting minikube directory located at {{.minikubePath}}",out.V{"minikubePath":localpath.MiniPath()}) + out.T(out.Meh, "Not deleting minikube directory located at {{.minikubePath}}", out.V{"minikubePath": localpath.MiniPath()}) } } From 65278fcb4d1a6c9efe5ae49d8dd2d2764e5db501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20F=20Bj=C3=B6rklund?= Date: Sun, 6 Oct 2019 20:07:20 +0200 Subject: [PATCH 11/78] Address some go9p issues adressed by SonarCloud --- third_party/go9p/ufs_darwin.go | 2 -- third_party/go9p/unpack.go | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/third_party/go9p/ufs_darwin.go b/third_party/go9p/ufs_darwin.go index eea436c5b8..da9a10fae2 100644 --- a/third_party/go9p/ufs_darwin.go +++ b/third_party/go9p/ufs_darwin.go @@ -23,14 +23,12 @@ func atime(stat *syscall.Stat_t) time.Time { func isBlock(d os.FileInfo) bool { stat := d.Sys().(*syscall.Stat_t) return (stat.Mode & syscall.S_IFMT) == syscall.S_IFBLK - return true } // IsChar reports if the file is a character device func isChar(d os.FileInfo) bool { stat := d.Sys().(*syscall.Stat_t) return (stat.Mode & syscall.S_IFMT) == syscall.S_IFCHR - return true } func dir2Qid(d os.FileInfo) *Qid { diff --git a/third_party/go9p/unpack.go b/third_party/go9p/unpack.go index 8c19e0bc2d..6871bd7ada 100644 --- a/third_party/go9p/unpack.go +++ b/third_party/go9p/unpack.go @@ -218,7 +218,7 @@ func Unpack(buf []byte, dotu bool) (fc *Fcall, err error, fcsz int) { goto szerror } - return + return //NOSONAR szerror: return nil, &Error{"invalid size", EINVAL}, 0 From fdf5345616567a538500c585c206c8903b554934 Mon Sep 17 00:00:00 2001 From: Josh Woodcock Date: Mon, 7 Oct 2019 09:18:43 -0500 Subject: [PATCH 12/78] Fix addons list output format option --- cmd/minikube/cmd/config/addons_list.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/minikube/cmd/config/addons_list.go b/cmd/minikube/cmd/config/addons_list.go index 72aadadc22..ddc207ae08 100644 --- a/cmd/minikube/cmd/config/addons_list.go +++ b/cmd/minikube/cmd/config/addons_list.go @@ -52,7 +52,7 @@ var addonsListCmd = &cobra.Command{ } func init() { - AddonsCmd.Flags().StringVar(&addonListFormat, "format", defaultAddonListFormat, + addonsListCmd.Flags().StringVar(&addonListFormat, "format", defaultAddonListFormat, `Go template format string for the addon list output. The format for Go templates can be found here: https://golang.org/pkg/text/template/ For the list of accessible variables for the template, see the struct values here: https://godoc.org/k8s.io/minikube/cmd/minikube/cmd/config#AddonListTemplate`) AddonsCmd.AddCommand(addonsListCmd) From 197215f85df3b7240466040984205417819162d4 Mon Sep 17 00:00:00 2001 From: Nanik T Date: Tue, 8 Oct 2019 09:02:43 +1100 Subject: [PATCH 13/78] Make error message more human readable Changes made: * service.go - changes to the error string returned * service_test.go - modify TestWaitAndMaybeOpenService test case to accomodate for the new changes --- pkg/minikube/service/service.go | 2 +- pkg/minikube/service/service_test.go | 51 ++++++++++++++++++++++++++-- test.sh | 2 +- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/pkg/minikube/service/service.go b/pkg/minikube/service/service.go index 710ca0ebfe..faabe06b2b 100644 --- a/pkg/minikube/service/service.go +++ b/pkg/minikube/service/service.go @@ -275,7 +275,7 @@ func WaitAndMaybeOpenService(api libmachine.API, namespace string, service strin chkSVC := func() error { return CheckService(namespace, service) } if err := retry.Expo(chkSVC, time.Duration(interval)*time.Second, time.Duration(wait)*time.Second); err != nil { - return errors.Wrapf(err, "Could not find finalized endpoint being pointed to by %s", service) + return errors.Wrapf(err, "Service %s was not found in default namespace , please try with 'minikube service %s -n Y'", service, service) } serviceURL, err := GetServiceURLsForService(api, namespace, service, urlTemplate) diff --git a/pkg/minikube/service/service_test.go b/pkg/minikube/service/service_test.go index 20b9f30fc0..be71633587 100644 --- a/pkg/minikube/service/service_test.go +++ b/pkg/minikube/service/service_test.go @@ -97,6 +97,29 @@ var serviceNamespaces = map[string]typed_core.ServiceInterface{ "default": defaultNamespaceServiceInterface, } +var nondefaultserviceNamespaces = map[string]typed_core.ServiceInterface{ + "default": nondefaultNamespaceServiceInterface, +} + + +var nondefaultNamespaceServiceInterface = &MockServiceInterface{ + ServiceList: &core.ServiceList{ + Items: []core.Service{ + { + ObjectMeta: meta.ObjectMeta{ + Name: "non-namespace-dashboard-no-ports", + Namespace: "non-default", + Labels: map[string]string{"mock": "mock"}, + }, + Spec: core.ServiceSpec{ + Ports: []core.ServicePort{}, + }, + }, + }, + }, +} + + var defaultNamespaceServiceInterface = &MockServiceInterface{ ServiceList: &core.ServiceList{ Items: []core.Service{ @@ -824,6 +847,7 @@ func TestWaitAndMaybeOpenService(t *testing.T) { urlMode bool https bool err bool + nondefault bool }{ /* { description: "no host", @@ -841,6 +865,7 @@ func TestWaitAndMaybeOpenService(t *testing.T) { api: defaultAPI, https: true, expected: []string{"http://127.0.0.1:1111", "http://127.0.0.1:2222"}, + nondefault: false, }, { description: "correctly return serviceURLs, no https, no url mode", @@ -848,6 +873,7 @@ func TestWaitAndMaybeOpenService(t *testing.T) { service: "mock-dashboard", api: defaultAPI, expected: []string{"http://127.0.0.1:1111", "http://127.0.0.1:2222"}, + nondefault: false, }, { description: "correctly return serviceURLs, no https, url mode", @@ -856,6 +882,7 @@ func TestWaitAndMaybeOpenService(t *testing.T) { api: defaultAPI, urlMode: true, expected: []string{"http://127.0.0.1:1111", "http://127.0.0.1:2222"}, + nondefault: false, }, { description: "correctly return serviceURLs, https, url mode", @@ -865,6 +892,7 @@ func TestWaitAndMaybeOpenService(t *testing.T) { urlMode: true, https: true, expected: []string{"http://127.0.0.1:1111", "http://127.0.0.1:2222"}, + nondefault: false, }, { description: "correctly return empty serviceURLs", @@ -873,14 +901,31 @@ func TestWaitAndMaybeOpenService(t *testing.T) { api: defaultAPI, expected: []string{}, err: true, + nondefault: false, + }, + { + description: "correctly return empty serviceURLs", + namespace: "default", + service: "non-namespace-dashboard-no-ports", + api: defaultAPI, + expected: []string{}, + err: true, + nondefault: true, }, } defer revertK8sClient(K8s) for _, test := range tests { t.Run(test.description, func(t *testing.T) { - K8s = &MockClientGetter{ - servicesMap: serviceNamespaces, - endpointsMap: endpointNamespaces, + if (test.nondefault) { + K8s = &MockClientGetter{ + servicesMap: nondefaultserviceNamespaces, + endpointsMap: endpointNamespaces, + } + } else { + K8s = &MockClientGetter{ + servicesMap: serviceNamespaces, + endpointsMap: endpointNamespaces, + } } err := WaitAndMaybeOpenService(test.api, test.namespace, test.service, defaultTemplate, test.urlMode, test.https, 1, 0) if test.err && err == nil { diff --git a/test.sh b/test.sh index c6173fb5b8..c48b4a1ef0 100755 --- a/test.sh +++ b/test.sh @@ -20,7 +20,7 @@ TESTSUITE="${TESTSUITE:-all}" # if env variable not set run all the tests exitcode=0 if [[ "$TESTSUITE" = "lint" ]] || [[ "$TESTSUITE" = "all" ]] -then +then echo "= make lint =============================================================" make -s lint-ci && echo ok || ((exitcode += 4)) echo "= go mod ================================================================" From 75ce59d500346058f4ea010f1b4d4bbae98f873e Mon Sep 17 00:00:00 2001 From: Nanik T Date: Tue, 8 Oct 2019 10:12:35 +1100 Subject: [PATCH 14/78] Fix linting --- pkg/minikube/service/service_test.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/pkg/minikube/service/service_test.go b/pkg/minikube/service/service_test.go index be71633587..30eb6be7c0 100644 --- a/pkg/minikube/service/service_test.go +++ b/pkg/minikube/service/service_test.go @@ -101,7 +101,6 @@ var nondefaultserviceNamespaces = map[string]typed_core.ServiceInterface{ "default": nondefaultNamespaceServiceInterface, } - var nondefaultNamespaceServiceInterface = &MockServiceInterface{ ServiceList: &core.ServiceList{ Items: []core.Service{ @@ -119,7 +118,6 @@ var nondefaultNamespaceServiceInterface = &MockServiceInterface{ }, } - var defaultNamespaceServiceInterface = &MockServiceInterface{ ServiceList: &core.ServiceList{ Items: []core.Service{ @@ -865,7 +863,7 @@ func TestWaitAndMaybeOpenService(t *testing.T) { api: defaultAPI, https: true, expected: []string{"http://127.0.0.1:1111", "http://127.0.0.1:2222"}, - nondefault: false, + nondefault: false, }, { description: "correctly return serviceURLs, no https, no url mode", @@ -873,7 +871,7 @@ func TestWaitAndMaybeOpenService(t *testing.T) { service: "mock-dashboard", api: defaultAPI, expected: []string{"http://127.0.0.1:1111", "http://127.0.0.1:2222"}, - nondefault: false, + nondefault: false, }, { description: "correctly return serviceURLs, no https, url mode", @@ -882,7 +880,7 @@ func TestWaitAndMaybeOpenService(t *testing.T) { api: defaultAPI, urlMode: true, expected: []string{"http://127.0.0.1:1111", "http://127.0.0.1:2222"}, - nondefault: false, + nondefault: false, }, { description: "correctly return serviceURLs, https, url mode", @@ -892,7 +890,7 @@ func TestWaitAndMaybeOpenService(t *testing.T) { urlMode: true, https: true, expected: []string{"http://127.0.0.1:1111", "http://127.0.0.1:2222"}, - nondefault: false, + nondefault: false, }, { description: "correctly return empty serviceURLs", @@ -901,7 +899,7 @@ func TestWaitAndMaybeOpenService(t *testing.T) { api: defaultAPI, expected: []string{}, err: true, - nondefault: false, + nondefault: false, }, { description: "correctly return empty serviceURLs", @@ -910,13 +908,13 @@ func TestWaitAndMaybeOpenService(t *testing.T) { api: defaultAPI, expected: []string{}, err: true, - nondefault: true, + nondefault: true, }, } defer revertK8sClient(K8s) for _, test := range tests { t.Run(test.description, func(t *testing.T) { - if (test.nondefault) { + if test.nondefault { K8s = &MockClientGetter{ servicesMap: nondefaultserviceNamespaces, endpointsMap: endpointNamespaces, From 733f7bc3f3d58c228c2bb1f6c0bcf19417ace61b Mon Sep 17 00:00:00 2001 From: Nanik T Date: Thu, 10 Oct 2019 07:13:47 +1100 Subject: [PATCH 15/78] Move the non-found-service test into separate function and modify the error text to include service name --- pkg/minikube/service/service.go | 2 +- pkg/minikube/service/service_test.go | 83 +++++++++++++++++++--------- 2 files changed, 57 insertions(+), 28 deletions(-) diff --git a/pkg/minikube/service/service.go b/pkg/minikube/service/service.go index faabe06b2b..fcc5bb7a7c 100644 --- a/pkg/minikube/service/service.go +++ b/pkg/minikube/service/service.go @@ -275,7 +275,7 @@ func WaitAndMaybeOpenService(api libmachine.API, namespace string, service strin chkSVC := func() error { return CheckService(namespace, service) } if err := retry.Expo(chkSVC, time.Duration(interval)*time.Second, time.Duration(wait)*time.Second); err != nil { - return errors.Wrapf(err, "Service %s was not found in default namespace , please try with 'minikube service %s -n Y'", service, service) + return errors.Wrapf(err, "Service %s was not found in %s namespace , please try with 'minikube service %s -n Y'", service, namespace, service) } serviceURL, err := GetServiceURLsForService(api, namespace, service, urlTemplate) diff --git a/pkg/minikube/service/service_test.go b/pkg/minikube/service/service_test.go index 30eb6be7c0..0d4d13fe57 100644 --- a/pkg/minikube/service/service_test.go +++ b/pkg/minikube/service/service_test.go @@ -97,7 +97,7 @@ var serviceNamespaces = map[string]typed_core.ServiceInterface{ "default": defaultNamespaceServiceInterface, } -var nondefaultserviceNamespaces = map[string]typed_core.ServiceInterface{ +var serviceNamespaceOther = map[string]typed_core.ServiceInterface{ "default": nondefaultNamespaceServiceInterface, } @@ -107,7 +107,7 @@ var nondefaultNamespaceServiceInterface = &MockServiceInterface{ { ObjectMeta: meta.ObjectMeta{ Name: "non-namespace-dashboard-no-ports", - Namespace: "non-default", + Namespace: "cannot_be_found_namespace", Labels: map[string]string{"mock": "mock"}, }, Spec: core.ServiceSpec{ @@ -845,7 +845,6 @@ func TestWaitAndMaybeOpenService(t *testing.T) { urlMode bool https bool err bool - nondefault bool }{ /* { description: "no host", @@ -863,7 +862,6 @@ func TestWaitAndMaybeOpenService(t *testing.T) { api: defaultAPI, https: true, expected: []string{"http://127.0.0.1:1111", "http://127.0.0.1:2222"}, - nondefault: false, }, { description: "correctly return serviceURLs, no https, no url mode", @@ -871,7 +869,6 @@ func TestWaitAndMaybeOpenService(t *testing.T) { service: "mock-dashboard", api: defaultAPI, expected: []string{"http://127.0.0.1:1111", "http://127.0.0.1:2222"}, - nondefault: false, }, { description: "correctly return serviceURLs, no https, url mode", @@ -880,7 +877,6 @@ func TestWaitAndMaybeOpenService(t *testing.T) { api: defaultAPI, urlMode: true, expected: []string{"http://127.0.0.1:1111", "http://127.0.0.1:2222"}, - nondefault: false, }, { description: "correctly return serviceURLs, https, url mode", @@ -890,7 +886,6 @@ func TestWaitAndMaybeOpenService(t *testing.T) { urlMode: true, https: true, expected: []string{"http://127.0.0.1:1111", "http://127.0.0.1:2222"}, - nondefault: false, }, { description: "correctly return empty serviceURLs", @@ -899,31 +894,65 @@ func TestWaitAndMaybeOpenService(t *testing.T) { api: defaultAPI, expected: []string{}, err: true, - nondefault: false, - }, - { - description: "correctly return empty serviceURLs", - namespace: "default", - service: "non-namespace-dashboard-no-ports", - api: defaultAPI, - expected: []string{}, - err: true, - nondefault: true, }, } defer revertK8sClient(K8s) for _, test := range tests { t.Run(test.description, func(t *testing.T) { - if test.nondefault { - K8s = &MockClientGetter{ - servicesMap: nondefaultserviceNamespaces, - endpointsMap: endpointNamespaces, - } - } else { - K8s = &MockClientGetter{ - servicesMap: serviceNamespaces, - endpointsMap: endpointNamespaces, - } + K8s = &MockClientGetter{ + servicesMap: serviceNamespaces, + endpointsMap: endpointNamespaces, + } + err := WaitAndMaybeOpenService(test.api, test.namespace, test.service, defaultTemplate, test.urlMode, test.https, 1, 0) + if test.err && err == nil { + t.Fatalf("WaitAndMaybeOpenService expected to fail for test: %v", test) + } + if !test.err && err != nil { + t.Fatalf("WaitAndMaybeOpenService not expected to fail but got err: %v", err) + } + + }) + } +} + +func TestWaitAndMaybeOpenServiceForNotDefaultNamspace(t *testing.T) { + defaultAPI := &tests.MockAPI{ + FakeStore: tests.FakeStore{ + Hosts: map[string]*host.Host{ + config.GetMachineName(): { + Name: config.GetMachineName(), + Driver: &tests.MockDriver{}, + }, + }, + }, + } + defaultTemplate := template.Must(template.New("svc-template").Parse("http://{{.IP}}:{{.Port}}")) + + var tests = []struct { + description string + api libmachine.API + namespace string + service string + expected []string + urlMode bool + https bool + err bool + }{ + { + description: "correctly return empty serviceURLs", + namespace: "default", + service: "non-namespace-dashboard-no-ports", + api: defaultAPI, + expected: []string{}, + err: true, + }, + } + defer revertK8sClient(K8s) + for _, test := range tests { + t.Run(test.description, func(t *testing.T) { + K8s = &MockClientGetter{ + servicesMap: serviceNamespaceOther, + endpointsMap: endpointNamespaces, } err := WaitAndMaybeOpenService(test.api, test.namespace, test.service, defaultTemplate, test.urlMode, test.https, 1, 0) if test.err && err == nil { From cd592172f0ecfddd1cda3a90e1f7c1af6d302fe6 Mon Sep 17 00:00:00 2001 From: tstromberg Date: Wed, 9 Oct 2019 13:48:05 -0700 Subject: [PATCH 16/78] Validate TCP connectivity to the VM --- cmd/minikube/cmd/start.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index 8ee66f820b..ed206a4ebb 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -912,7 +912,17 @@ func validateNetwork(h *host.Host) string { } } - // Here is where we should be checking connectivity to/from the VM + // none driver should not require ssh or any other open ports + if h.Driver.DriverName() == constants.DriverNone { + return ip + } + + sshAddr := fmt.Sprintf("%s:22", ip) + conn, err := net.Dial("tcp", sshAddr) + if err != nil { + exit.WithCodeT(exit.IO, "Unable to contact VM at {{.address}}: {{.error}}", out.V{"address": sshAddr, "error": err}) + } + defer conn.Close() return ip } From fb0d042710cc91adfc1767843878d2d0873031c2 Mon Sep 17 00:00:00 2001 From: tstromberg Date: Wed, 9 Oct 2019 15:24:42 -0700 Subject: [PATCH 17/78] Attempt a better error message --- cmd/minikube/cmd/start.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index c4a3b3cf6b..e2fcdda819 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -923,10 +923,10 @@ func validateNetwork(h *host.Host) string { return ip } - sshAddr := fmt.Sprintf("%s:22", ip) + sshAddr := fmt.Sprintf("%s:22000", ip) conn, err := net.Dial("tcp", sshAddr) if err != nil { - exit.WithCodeT(exit.IO, "Unable to contact VM at {{.address}}: {{.error}}", out.V{"address": sshAddr, "error": err}) + exit.WithCodeT(exit.IO, "Unable to contact {{.hypervisor}} \"{{.name}}\" VM: {{.error}}\n\nIf you have a VPN or firewall enabled, try turning it off or configuring it so that it does not capture packets sent to {{.ip}}.\n\nAlso, check the {{.hypervisor}} network preferences and/or reboot your machine", out.V{"name": cfg.GetMachineName(), "error": err, "hypervisor": h.Driver.DriverName()}) } defer conn.Close() return ip From 7834c83d9d576a4dcb28ea41249a1e6d415fa437 Mon Sep 17 00:00:00 2001 From: BlackHole1 <158blackhole@gmail.com> Date: Tue, 27 Aug 2019 09:40:55 +0800 Subject: [PATCH 18/78] optimizing Chinese translation (No.2) --- translations/zh-CN.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/translations/zh-CN.json b/translations/zh-CN.json index 6af65586d7..847c6e1e2c 100644 --- a/translations/zh-CN.json +++ b/translations/zh-CN.json @@ -151,10 +151,10 @@ "Failed to delete images from config": "", "Failed to download kubectl": "", "Failed to enable container runtime": "", - "Failed to generate config": "", - "Failed to get bootstrapper": "", + "Failed to generate config": "无法生成 config", + "Failed to get bootstrapper": "获取 bootstrapper 失败", "Failed to get command runner": "", - "Failed to get driver URL": "", + "Failed to get driver URL": "获取 driver URL 失败", "Failed to get image map": "", "Failed to get machine client": "", "Failed to get service URL: {{.error}}": "", From 910a69eec32c593ecd5304a3ed9952ae95997ba1 Mon Sep 17 00:00:00 2001 From: BlackHole1 <158blackhole@gmail.com> Date: Thu, 10 Oct 2019 09:47:03 +0800 Subject: [PATCH 19/78] refactor(i18n): add chinese translation --- translations/zh-CN.json | 274 ++++++++++++++++++++-------------------- 1 file changed, 137 insertions(+), 137 deletions(-) diff --git a/translations/zh-CN.json b/translations/zh-CN.json index 847c6e1e2c..777e14862a 100644 --- a/translations/zh-CN.json +++ b/translations/zh-CN.json @@ -1,155 +1,155 @@ { - "\"{{.minikube_addon}}\" was successfully disabled": "", - "\"{{.name}}\" cluster does not exist. Proceeding ahead with cleanup.": "", + "\"{{.minikube_addon}}\" was successfully disabled": "已成功禁用 \"{{.minikube_addon}}\"", + "\"{{.name}}\" cluster does not exist. Proceeding ahead with cleanup.": "\"{{.name}}\" 集群不存在,将继续清理", "\"{{.name}}\" profile does not exist": "“{{.name}}”配置文件不存在", - "\"{{.profile_name}}\" VM does not exist, nothing to stop": "", - "\"{{.profile_name}}\" host does not exist, unable to show an IP": "", - "\"{{.profile_name}}\" stopped.": "", - "'none' driver does not support 'minikube docker-env' command": "", - "'none' driver does not support 'minikube mount' command": "", - "'none' driver does not support 'minikube ssh' command": "", - "A VPN or firewall is interfering with HTTP access to the minikube VM. Alternatively, try a different VM driver: https://minikube.sigs.k8s.io/docs/start/": "", - "A firewall is blocking Docker within the minikube VM from reaching the internet. You may need to configure it to use a proxy.": "", - "A firewall is interfering with minikube's ability to make outgoing HTTPS requests. You may need to change the value of the HTTPS_PROXY environment variable.": "", - "A firewall is likely blocking minikube from reaching the internet. You may need to configure minikube to use a proxy.": "", - "A set of apiserver IP Addresses which are used in the generated certificate for kubernetes. This can be used if you want to make the apiserver available from outside the machine": "", + "\"{{.profile_name}}\" VM does not exist, nothing to stop": "\"{{.profile_name}}\" 虚拟机不存在,没有什么可供停止的", + "\"{{.profile_name}}\" host does not exist, unable to show an IP": "\"{{.profile_name}}\" 主机不存在,无法显示其IP", + "\"{{.profile_name}}\" stopped.": "\"{{.profile_name}}\" 已停止", + "'none' driver does not support 'minikube docker-env' command": "'none' 驱动不支持 'minikube docker-env' 命令", + "'none' driver does not support 'minikube mount' command": "'none' 驱动不支持 'minikube mount' 命令", + "'none' driver does not support 'minikube ssh' command": "'none' 驱动不支持 'minikube ssh' 命令", + "A VPN or firewall is interfering with HTTP access to the minikube VM. Alternatively, try a different VM driver: https://minikube.sigs.k8s.io/docs/start/": "VPN 或者防火墙正在干扰对 minikube 虚拟机的 HTTP 访问。或者,您可以使用其它的虚拟机驱动:https://minikube.sigs.k8s.io/docs/start/", + "A firewall is blocking Docker within the minikube VM from reaching the internet. You may need to configure it to use a proxy.": "防火墙正在阻止 minikube 虚拟机中的 Docker 访问互联网,您可能需要对其进行配置为使用代理", + "A firewall is interfering with minikube's ability to make outgoing HTTPS requests. You may need to change the value of the HTTPS_PROXY environment variable.": "防火墙正在干扰 minikube 发送 HTTPS 请求的能力,您可能需要改变 HTTPS_PROXY 环境变量的值", + "A firewall is likely blocking minikube from reaching the internet. You may need to configure minikube to use a proxy.": "防火墙可能会阻止 minikube 访问互联网。您可能需要将 minikube 配置为使用", + "A set of apiserver IP Addresses which are used in the generated certificate for kubernetes. This can be used if you want to make the apiserver available from outside the machine": "一组在为 kubernetes 生成的证书中使用的 apiserver IP 地址。如果您希望将此 apiserver 设置为可从机器外部访问,则可以使用这组 apiserver IP 地址", "A set of apiserver IP Addresses which are used in the generated certificate for kubernetes. This can be used if you want to make the apiserver available from outside the machine": "一组在为 kubernetes 生成的证书中使用的 apiserver IP 地址。如果您希望将此 apiserver 设置为可从机器外部访问,则可以使用这组 apiserver IP 地址", - "A set of apiserver names which are used in the generated certificate for kubernetes. This can be used if you want to make the apiserver available from outside the machine": "", + "A set of apiserver names which are used in the generated certificate for kubernetes. This can be used if you want to make the apiserver available from outside the machine": "一组在为 kubernetes 生成的证书中使用的 apiserver 名称。如果您希望将此 apiserver 设置为可从机器外部访问,则可以使用这组 apiserver 名称", "A set of apiserver names which are used in the generated certificate for kubernetes. This can be used if you want to make the apiserver available from outside the machine": "一组在为 kubernetes 生成的证书中使用的 apiserver 名称。如果您希望将此 apiserver 设置为可从机器外部访问,则可以使用这组 apiserver 名称", "A set of key=value pairs that describe configuration that may be passed to different components.\nThe key should be '.' separated, and the first part before the dot is the component to apply the configuration to.\nValid components are: kubelet, kubeadm, apiserver, controller-manager, etcd, proxy, scheduler\nValid kubeadm parameters:": "一组用于描述可传递给不同组件的配置的键值对。\n其中键应以英文句点“.”分隔,英文句点前面的第一个部分是应用该配置的组件。\n有效组件包括:kubelet、kubeadm、apiserver、controller-manager、etcd、proxy、scheduler\n有效 kubeadm 参数包括:", "A set of key=value pairs that describe feature gates for alpha/experimental features.": "一组用于描述 alpha 版功能/实验性功能的功能限制的键值对。", - "Access the kubernetes dashboard running within the minikube cluster": "", - "Add an image to local cache.": "", - "Add machine IP to NO_PROXY environment variable": "", - "Add or delete an image from the local cache.": "", - "Additional help topics": "", - "Additional mount options, such as cache=fscache": "", - "Advanced Commands:": "", - "Aliases": "", - "Allow user prompts for more information": "", + "Access the kubernetes dashboard running within the minikube cluster": "访问在 minikube 集群中运行的 kubernetes dashboard", + "Add an image to local cache.": "将 image 添加到本地缓存。", + "Add machine IP to NO_PROXY environment variable": "将机器IP添加到环境变量 NO_PROXY 中", + "Add or delete an image from the local cache.": "在本地缓存中添加或删除 image。", + "Additional help topics": "其他帮助", + "Additional mount options, such as cache=fscache": "其他挂载选项,例如:cache=fscache", + "Advanced Commands:": "高级命令:", + "Aliases": "别名", + "Allow user prompts for more information": "允许用户提示以获取更多信息", "Alternative image repository to pull docker images from. This can be used when you have limited access to gcr.io. Set it to \\\"auto\\\" to let minikube decide one for you. For Chinese mainland users, you may use local gcr.io mirrors such as registry.cn-hangzhou.aliyuncs.com/google_containers": "用于从中拉取 docker 映像的备选映像存储库。如果您对 gcr.io 的访问受到限制,则可以使用该映像存储库。将映像存储库设置为“auto”可让 minikube 为您选择一个存储库。对于中国大陆用户,您可以使用本地 gcr.io 镜像,例如 registry.cn-hangzhou.aliyuncs.com/google_containers", "Amount of RAM allocated to the minikube VM (format: \u003cnumber\u003e[\u003cunit\u003e], where unit = b, k, m or g)": "为 minikube 虚拟机分配的 RAM 容量(格式:\u003c数字\u003e[\u003c单位\u003e],其中单位 = b、k、m 或 g)", - "Amount of RAM allocated to the minikube VM (format: \u003cnumber\u003e[\u003cunit\u003e], where unit = b, k, m or g).": "", - "Amount of time to wait for a service in seconds": "", - "Amount of time to wait for service in seconds": "", - "Available Commands": "", - "Basic Commands:": "", - "Cannot find directory {{.path}} for mount": "", - "Check that minikube is running and that you have specified the correct namespace (-n flag) if required.": "", - "Check that your --kubernetes-version has a leading 'v'. For example: 'v1.1.14'": "", - "Check that your apiserver flags are valid, or run 'minikube delete'": "", - "Check your firewall rules for interference, and run 'virt-host-validate' to check for KVM configuration issues. If you are running minikube within a VM, consider using --vm-driver=none": "", - "Configuration and Management Commands:": "", - "Configure an external network switch following the official documentation, then add `--hyperv-virtual-switch=\u003cswitch-name\u003e` to `minikube start`": "", - "Configures the addon w/ADDON_NAME within minikube (example: minikube addons configure registry-creds). For a list of available addons use: minikube addons list": "", + "Amount of RAM allocated to the minikube VM (format: \u003cnumber\u003e[\u003cunit\u003e], where unit = b, k, m or g).": "为 minikube 虚拟机分配的 RAM 容量(格式:\u003c数字\u003e[\u003c单位\u003e],其中单位 = b、k、m 或 g)。", + "Amount of time to wait for a service in seconds": "等待服务的时间(单位秒)", + "Amount of time to wait for service in seconds": "等待服务的时间(单位秒)", + "Available Commands": "可用命令", + "Basic Commands:": "基本命令:", + "Cannot find directory {{.path}} for mount": "找不到用来挂载的 {{.path}} 目录", + "Check that minikube is running and that you have specified the correct namespace (-n flag) if required.": "检测 minikube 是否正在运行,以及是否根据需要指定了正确的 namespace (-n 标志)", + "Check that your --kubernetes-version has a leading 'v'. For example: 'v1.1.14'": "检测您的 --kubernetes-version 前面是否有 'v', 例如:'v1.1.14", + "Check that your apiserver flags are valid, or run 'minikube delete'": "请检查您的 apiserver 标志是否有效,或者允许 'minikube delete'", + "Check your firewall rules for interference, and run 'virt-host-validate' to check for KVM configuration issues. If you are running minikube within a VM, consider using --vm-driver=none": "检查您的防火墙规则是否存在干扰,然后运行 'virt-host-validate' 以检查 KVM 配置问题,如果在虚拟机中运行minikube,请考虑使用 --vm-driver=none", + "Configuration and Management Commands:": "配置和管理命令:", + "Configure an external network switch following the official documentation, then add `--hyperv-virtual-switch=\u003cswitch-name\u003e` to `minikube start`": "根据官方文档配置外部网络交换机,然后添加 `--hyperv-virtual-switch=\u003cswitch-name\u003e` 到 `minikube start`", + "Configures the addon w/ADDON_NAME within minikube (example: minikube addons configure registry-creds). For a list of available addons use: minikube addons list": "在 minikube 中配置插件 w/ADDON_NAME(例如:minikube addons configure registry-creds)。查看相关可用的插件列表,请使用:minikube addons list", "Configuring environment for Kubernetes {{.k8sVersion}} on {{.runtime}} {{.runtimeVersion}}": "开始为Kubernetes {{.k8sVersion}},{{.runtime}} {{.runtimeVersion}} 配置环境变量", - "Configuring local host environment ...": "", - "Confirm that you have a working internet connection and that your VM has not run out of resources by using: 'minikube logs'": "", - "Confirm that you have supplied the correct value to --hyperv-virtual-switch using the 'Get-VMSwitch' command": "", + "Configuring local host environment ...": "开始配置本地主机环境...", + "Confirm that you have a working internet connection and that your VM has not run out of resources by using: 'minikube logs'": "使用 'minikube logs' 确认您的互联网连接正常,并且您的虚拟机没有耗尽资源", + "Confirm that you have supplied the correct value to --hyperv-virtual-switch using the 'Get-VMSwitch' command": "使用 'Get-VMSwitch' 命令确认已经为 --hyperv-virtual-switch 提供了正确的值", "Country code of the image mirror to be used. Leave empty to use the global one. For Chinese mainland users, set it to cn.": "需要使用的映像镜像的国家/地区代码。留空以使用全球代码。对于中国大陆用户,请将其设置为 cn。", - "Created a new profile : {{.profile_name}}": "", - "Creating a new profile failed": "", + "Created a new profile : {{.profile_name}}": "创建了新的配置文件:{{.profile_name}}", + "Creating a new profile failed": "创建新的配置文件失败", "Creating mount {{.name}} ...": "正在创建装载 {{.name}}…", - "Creating {{.driver_name}} VM (CPUs={{.number_of_cpus}}, Memory={{.memory_size}}MB, Disk={{.disk_size}}MB) ...": "", - "Default group id used for the mount": "", - "Default user id used for the mount": "", - "Delete an image from the local cache.": "", - "Deletes a local kubernetes cluster": "", - "Deletes a local kubernetes cluster. This command deletes the VM, and removes all\nassociated files.": "", + "Creating {{.driver_name}} VM (CPUs={{.number_of_cpus}}, Memory={{.memory_size}}MB, Disk={{.disk_size}}MB) ...": "正在创建 {{.driver_name}} 虚拟机(CPUs={{.number_of_cpus}},Memory={{.memory_size}}MB, Disk={{.disk_size}}MB)...", + "Default group id used for the mount": "用于挂载默认的 group id", + "Default user id used for the mount": "用于挂载默认的 user id", + "Delete an image from the local cache.": "从本地缓存中删除 image。", + "Deletes a local kubernetes cluster": "删除本地的 kubernetes 集群", + "Deletes a local kubernetes cluster. This command deletes the VM, and removes all\nassociated files.": "删除本地的 kubernetes 集群。此命令还将删除虚拟机,并删除所有的\n相关文件", "Deletes a local kubernetes cluster. This command deletes the VM, and removes all associated files.": "删除本地 kubernetes 集群。此命令会删除虚拟机并移除所有关联的文件。", "Deleting \"{{.profile_name}}\" in {{.driver_name}} ...": "正在删除 {{.driver_name}} 中的“{{.profile_name}}”…", "Disable checking for the availability of hardware virtualization before the vm is started (virtualbox driver only)": "禁用在启动虚拟机之前检查硬件虚拟化的可用性(仅限 virtualbox 驱动程序)", - "Disable dynamic memory in your VM manager, or pass in a larger --memory value": "", - "Disables the addon w/ADDON_NAME within minikube (example: minikube addons disable dashboard). For a list of available addons use: minikube addons list": "", + "Disable dynamic memory in your VM manager, or pass in a larger --memory value": "禁用虚拟机管理器中的动态内存,或者使用 --memory 传入更大的值", + "Disables the addon w/ADDON_NAME within minikube (example: minikube addons disable dashboard). For a list of available addons use: minikube addons list": "在 minikube 中禁用插件 w/ADDON_NAME(例如:minikube addons disable dashboard)。查看相关可用的插件列表,请使用:minikube addons list", "Disables the filesystem mounts provided by the hypervisors": "停用由管理程序提供的文件系统装载", "Disk size allocated to the minikube VM (format: \u003cnumber\u003e[\u003cunit\u003e], where unit = b, k, m or g)": "分配给 minikube 虚拟机的磁盘大小(格式:\u003c数字\u003e[\u003c单位\u003e],其中单位 = b、k、m 或 g)", - "Disk size allocated to the minikube VM (format: \u003cnumber\u003e[\u003cunit\u003e], where unit = b, k, m or g).": "", - "Display dashboard URL instead of opening a browser": "", - "Display the kubernetes addons URL in the CLI instead of opening it in the default browser": "", - "Display the kubernetes service URL in the CLI instead of opening it in the default browser": "", - "Display values currently set in the minikube config file": "", - "Display values currently set in the minikube config file.": "", - "Docker inside the VM is unavailable. Try running 'minikube delete' to reset the VM.": "", - "Docs have been saved at - {{.path}}": "", - "Documentation: {{.url}}": "", - "Done! kubectl is now configured to use \"{{.name}}\"": "", + "Disk size allocated to the minikube VM (format: \u003cnumber\u003e[\u003cunit\u003e], where unit = b, k, m or g).": "分配给 minikube 虚拟机的磁盘大小(格式:\u003c数字\u003e[\u003c单位\u003e],其中单位 = b、k、m 或 g)。", + "Display dashboard URL instead of opening a browser": "显示 dashboard URL,而不是打开浏览器", + "Display the kubernetes addons URL in the CLI instead of opening it in the default browser": "在终端中显示 kubernetes addons URL,而不是在默认浏览器中打开它", + "Display the kubernetes service URL in the CLI instead of opening it in the default browser": "在终端中显示 kubernetes service URL,而不是在默认浏览器中打开它", + "Display values currently set in the minikube config file": "显示当前在 minikube 配置文件中设置的值", + "Display values currently set in the minikube config file.": "显示当前在 minikube 配置文件中设置的值。", + "Docker inside the VM is unavailable. Try running 'minikube delete' to reset the VM.": "虚拟机中的 Docker 不可用,尝试运行 'minikube delete' 来重置虚拟机。", + "Docs have been saved at - {{.path}}": "文档已保存在 - {{.path}}", + "Documentation: {{.url}}": "文档:{{.url}}", + "Done! kubectl is now configured to use \"{{.name}}\"": "完成!kubectl 已经配置至 \"{{.name}}\"", "Done! kubectl is now configured to use {{.name}}": "完成!kubectl已经配置至{{.name}}", "Download complete!": "下载完成!", - "Downloading VM boot image ...": "", - "Downloading driver {{.driver}}:": "", - "Downloading {{.name}} {{.version}}": "", - "ERROR creating `registry-creds-dpr` secret": "", - "ERROR creating `registry-creds-ecr` secret: {{.error}}": "", - "ERROR creating `registry-creds-gcr` secret: {{.error}}": "", - "Either systemctl is not installed, or Docker is broken. Run 'sudo systemctl start docker' and 'journalctl -u docker'": "", + "Downloading VM boot image ...": "正在下载 VM boot image...", + "Downloading driver {{.driver}}:": "正在下载驱动 {{.driver}}:", + "Downloading {{.name}} {{.version}}": "正在下载 {{.name}} {{.version}}", + "ERROR creating `registry-creds-dpr` secret": "创建 `registry-creds-dpr` secret 时出错", + "ERROR creating `registry-creds-ecr` secret: {{.error}}": "创建 `registry-creds-ecr` secret 时出错:{{.error}}", + "ERROR creating `registry-creds-gcr` secret: {{.error}}": "创建 `registry-creds-gcr` secret 时出错:{{.error}}", + "Either systemctl is not installed, or Docker is broken. Run 'sudo systemctl start docker' and 'journalctl -u docker'": "未安装 systemctl 或者 Docker 损坏。请运行 'sudo systemctl start docker' 和 'journalctl -u docker'", "Enable experimental NVIDIA GPU support in minikube": "在 minikube 中启用实验性 NVIDIA GPU 支持", "Enable host resolver for NAT DNS requests (virtualbox driver only)": "为 NAT DNS 请求启用主机解析器(仅限 virtualbox 驱动程序)", "Enable proxy for NAT DNS requests (virtualbox driver only)": "为 NAT DNS 请求启用代理(仅限 virtualbox 驱动程序)", "Enable the default CNI plugin (/etc/cni/net.d/k8s.conf). Used in conjunction with \\\"--network-plugin=cni\\": "启用默认 CNI 插件 (/etc/cni/net.d/k8s.conf)。与“--network-plugin=cni”结合使用", - "Enable the default CNI plugin (/etc/cni/net.d/k8s.conf). Used in conjunction with \\\"--network-plugin=cni\\\".": "", - "Enables the addon w/ADDON_NAME within minikube (example: minikube addons enable dashboard). For a list of available addons use: minikube addons list": "", - "Enabling dashboard ...": "", + "Enable the default CNI plugin (/etc/cni/net.d/k8s.conf). Used in conjunction with \\\"--network-plugin=cni\\\".": "启用默认 CNI 插件 (/etc/cni/net.d/k8s.conf)。与“--network-plugin=cni”结合使用。", + "Enables the addon w/ADDON_NAME within minikube (example: minikube addons enable dashboard). For a list of available addons use: minikube addons list": "启动 minikube 插件 w/ADDON_NAME(例如:minikube addons enable dashboard)。查看相关可用的插件列表,请使用:minikube addons list", + "Enabling dashboard ...": "正在开启 dashboard ...", "Environment variables to pass to the Docker daemon. (format: key=value)": "传递给 Docker 守护进程的环境变量。(格式:键值对)", "Error checking driver version: {{.error}}": "检查驱动程序版本时出错:{{.error}}", - "Error creating list template": "", - "Error creating minikube directory": "", - "Error creating status template": "", - "Error creating view template": "", - "Error executing list template": "", - "Error executing status template": "", - "Error executing template": "", - "Error executing view template": "", - "Error finding port for mount": "", - "Error getting IP": "", - "Error getting bootstrapper": "", - "Error getting client": "", - "Error getting client: {{.error}}": "", - "Error getting cluster": "", - "Error getting cluster bootstrapper": "", - "Error getting config": "", - "Error getting host": "", - "Error getting host status": "", - "Error getting machine logs": "", - "Error getting machine status": "", - "Error getting service status": "", - "Error getting service with namespace: {{.namespace}} and labels {{.labelName}}:{{.addonName}}: {{.error}}": "", - "Error getting the host IP address to use from within the VM": "", + "Error creating list template": "创建 list template 时出错", + "Error creating minikube directory": "创建 minikube 目录时出错", + "Error creating status template": "创建 status template 时出错", + "Error creating view template": "创建 view template 时出错", + "Error executing list template": "执行 list template 时出错", + "Error executing status template": "执行 status template 时出错", + "Error executing template": "执行 template 时出错", + "Error executing view template": "执行 view template 时出错", + "Error finding port for mount": "查找 mount 端口时出错", + "Error getting IP": "获取 IP 时出错", + "Error getting bootstrapper": "获取 bootstrapper 时出错", + "Error getting client": "获取 client 时出错", + "Error getting client: {{.error}}": "获取 client 时出错:{{.error}}", + "Error getting cluster": "获取 cluster 时出错", + "Error getting cluster bootstrapper": "获取 cluster bootstrapper 时出错", + "Error getting config": "获取 config 时出错", + "Error getting host": "获取 host 时出错", + "Error getting host status": "获取 host status 时出错", + "Error getting machine logs": "获取 machine logs 时出错", + "Error getting machine status": "获取 machine status 时出错", + "Error getting service status": "获取 service status 时出错", + "Error getting service with namespace: {{.namespace}} and labels {{.labelName}}:{{.addonName}}: {{.error}}": "使用 namespace: {{.namespace}} 和 labels {{.labelName}}:{{.addonName}} 获取 service 时出错:{{.error}}", + "Error getting the host IP address to use from within the VM": "从虚拟机中获取 host IP 地址时出错", "Error host driver ip status": "", - "Error killing mount process": "", - "Error loading api": "", - "Error loading profile config": "", - "Error loading profile config: {{.error}}": "", + "Error killing mount process": "杀死 mount 进程时出错", + "Error loading api": "加载 api 时出错", + "Error loading profile config": "加载配置文件的配置时出错", + "Error loading profile config: {{.error}}": "加载配置文件的配置时出错:{{.error}}", "Error loading profile {{.name}}: {{.error}}": "加载配置文件 {{.name}} 时出错:{{.error}}", - "Error opening service": "", + "Error opening service": "开启 service 时出错", "Error parsing minikube version: {{.error}}": "解析 minikube 版本时出错:{{.error}}", "Error parsing vmDriver version: {{.error}}": "解析 vmDriver 版本时出错:{{.error}}", - "Error reading {{.path}}: {{.error}}": "", - "Error restarting cluster": "", - "Error setting shell variables": "", - "Error starting cluster": "", - "Error starting mount": "", - "Error unsetting shell variables": "", - "Error while setting kubectl current context : {{.error}}": "", - "Error writing mount pid": "", - "Error: You have selected Kubernetes v{{.new}}, but the existing cluster for your profile is running Kubernetes v{{.old}}. Non-destructive downgrades are not supported, but you can proceed by performing one of the following options:\n\n* Recreate the cluster using Kubernetes v{{.new}}: Run \"minikube delete {{.profile}}\", then \"minikube start {{.profile}} --kubernetes-version={{.new}}\"\n* Create a second cluster with Kubernetes v{{.new}}: Run \"minikube start -p \u003cnew name\u003e --kubernetes-version={{.new}}\"\n* Reuse the existing cluster with Kubernetes v{{.old}} or newer: Run \"minikube start {{.profile}} --kubernetes-version={{.old}}\"": "", + "Error reading {{.path}}: {{.error}}": "读取 {{.path}} 时出错:{{.error}}", + "Error restarting cluster": "重启 cluster 时出错", + "Error setting shell variables": "设置 shell 变量时出错", + "Error starting cluster": "开启 cluster 时出错", + "Error starting mount": "开启 mount 时出错", + "Error unsetting shell variables": "取消设置 shell 变量时出错", + "Error while setting kubectl current context : {{.error}}": "设置 kubectl 上下文时出错 :{{.error}}", + "Error writing mount pid": "写入 mount pid 时出错", + "Error: You have selected Kubernetes v{{.new}}, but the existing cluster for your profile is running Kubernetes v{{.old}}. Non-destructive downgrades are not supported, but you can proceed by performing one of the following options:\n\n* Recreate the cluster using Kubernetes v{{.new}}: Run \"minikube delete {{.profile}}\", then \"minikube start {{.profile}} --kubernetes-version={{.new}}\"\n* Create a second cluster with Kubernetes v{{.new}}: Run \"minikube start -p \u003cnew name\u003e --kubernetes-version={{.new}}\"\n* Reuse the existing cluster with Kubernetes v{{.old}} or newer: Run \"minikube start {{.profile}} --kubernetes-version={{.old}}\"": "错误:您已选择 Kubernetes v{{.new}},但您的配置文件的现有集群正在运行 Kubernetes v{{.old}}。非破坏性降级不受支持,但若要继续操作,您可以执行以下选项之一:\n\n* 使用 Kubernetes v{{.new}} 重新创建现有集群:运行“minikube delete {{.profile}}”,然后运行“minikube start {{.profile}} --kubernetes-version={{.new}}”\n* 使用 Kubernetes v{{.new}} 再创建一个集群:运行“minikube start -p \u003cnew name\u003e --kubernetes-version={{.new}}”\n* 通过 Kubernetes v{{.old}} 或更高版本重复使用现有集群:运行“minikube start {{.profile}} --kubernetes-version={{.old}}”", "Error: You have selected Kubernetes v{{.new}}, but the existing cluster for your profile is running Kubernetes v{{.old}}. Non-destructive downgrades are not supported, but you can proceed by performing one of the following options:\n* Recreate the cluster using Kubernetes v{{.new}}: Run \"minikube delete {{.profile}}\", then \"minikube start {{.profile}} --kubernetes-version={{.new}}\"\n* Create a second cluster with Kubernetes v{{.new}}: Run \"minikube start -p \u003cnew name\u003e --kubernetes-version={{.new}}\"\n* Reuse the existing cluster with Kubernetes v{{.old}} or newer: Run \"minikube start {{.profile}} --kubernetes-version={{.old}}": "错误:您已选择 Kubernetes v{{.new}},但您的配置文件的现有集群正在运行 Kubernetes v{{.old}}。非破坏性降级不受支持,但若要继续操作,您可以执行以下选项之一:\n* 使用 Kubernetes v{{.new}} 重新创建现有集群:运行“minikube delete {{.profile}}”,然后运行“minikube start {{.profile}} --kubernetes-version={{.new}}”\n* 使用 Kubernetes v{{.new}} 再创建一个集群:运行“minikube start -p \u003cnew name\u003e --kubernetes-version={{.new}}”\n* 通过 Kubernetes v{{.old}} 或更高版本重复使用现有集群:运行“minikube start {{.profile}} --kubernetes-version={{.old}}”", - "Error: [{{.id}}] {{.error}}": "", - "Examples": "", + "Error: [{{.id}}] {{.error}}": "错误:[{{.id}}] {{.error}}", + "Examples": "示例", "Exiting": "正在退出", - "Exiting due to driver incompatibility": "", + "Exiting due to driver incompatibility": "由于驱动程序不兼容而退出", "Failed runtime": "", - "Failed to cache ISO": "", - "Failed to cache and load images": "", - "Failed to cache binaries": "", - "Failed to cache images": "", + "Failed to cache ISO": "缓存ISO 时失败", + "Failed to cache and load images": "无法加载 cache 和 images", + "Failed to cache binaries": "缓存二进制文件失败", + "Failed to cache images": "缓存 images 时失败", "Failed to change permissions for {{.minikube_dir_path}}: {{.error}}": "未能更改 {{.minikube_dir_path}} 的权限:{{.error}}", - "Failed to check if machine exists": "", - "Failed to check main repository and mirrors for images for images": "", + "Failed to check if machine exists": "无法检测机器是否存在", + "Failed to check main repository and mirrors for images for images": "无法检测主 repository 和 mirrors images 中的 images", "Failed to delete cluster: {{.error}}": "未能删除集群:{{.error}}", "Failed to delete cluster: {{.error}}__1": "未能删除集群:{{.error}}", - "Failed to delete images": "", - "Failed to delete images from config": "", - "Failed to download kubectl": "", + "Failed to delete images": "删除 images 时失败", + "Failed to delete images from config": "无法从 config 里删除 images", + "Failed to download kubectl": "下载 kubectl 失败", "Failed to enable container runtime": "", "Failed to generate config": "无法生成 config", "Failed to get bootstrapper": "获取 bootstrapper 失败", @@ -157,32 +157,32 @@ "Failed to get driver URL": "获取 driver URL 失败", "Failed to get image map": "", "Failed to get machine client": "", - "Failed to get service URL: {{.error}}": "", + "Failed to get service URL: {{.error}}": "获取 service URL 失败:{{.error}}", "Failed to kill mount process: {{.error}}": "未能终止装载进程:{{.error}}", - "Failed to list cached images": "", - "Failed to remove profile": "", - "Failed to save config": "", + "Failed to list cached images": "无法列出缓存镜像", + "Failed to remove profile": "无法删除配置文件", + "Failed to save config": "无法保存配置", "Failed to set NO_PROXY Env. Please use `export NO_PROXY=$NO_PROXY,{{.ip}}": "未能设置 NO_PROXY 环境变量。请使用“export NO_PROXY=$NO_PROXY,{{.ip}}”", - "Failed to set NO_PROXY Env. Please use `export NO_PROXY=$NO_PROXY,{{.ip}}`.": "", - "Failed to setup certs": "", - "Failed to setup kubeconfig": "", - "Failed to update cluster": "", - "Failed to update config": "", - "Failed unmount: {{.error}}": "", - "File permissions used for the mount": "", - "Flags": "", - "Follow": "", + "Failed to set NO_PROXY Env. Please use `export NO_PROXY=$NO_PROXY,{{.ip}}`.": "未能设置 NO_PROXY 环境变量。请使用“export NO_PROXY=$NO_PROXY,{{.ip}}”。", + "Failed to setup certs": "设置 certs 失败", + "Failed to setup kubeconfig": "设置 kubeconfig 失败", + "Failed to update cluster": "更新 cluster 失败", + "Failed to update config": "更新 config 失败", + "Failed unmount: {{.error}}": "unmount 失败:{{.error}}", + "File permissions used for the mount": "用于 mount 的文件权限", + "Flags": "标志", + "Follow": "跟踪", "For best results, install kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/": "为获得最佳结果,请安装 kubectl:https://kubernetes.io/docs/tasks/tools/install-kubectl/", "For best results, install kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/__1": "为获得最佳结果,请安装 kubectl:https://kubernetes.io/docs/tasks/tools/install-kubectl/", "For more information, see:": "如需了解详情,请参阅:", - "Force environment to be configured for a specified shell: [fish, cmd, powershell, tcsh, bash, zsh], default is auto-detect": "", + "Force environment to be configured for a specified shell: [fish, cmd, powershell, tcsh, bash, zsh], default is auto-detect": "强制为指定的 shell 配置环境:[fish, cmd, powershell, tcsh, bash, zsh],默认为 auto-detect", "Force minikube to perform possibly dangerous operations": "强制 minikube 执行可能有风险的操作", "Found network options:": "找到的网络选项:", - "Found {{.number}} invalid profile(s) !": "", - "Gets the kubernetes URL(s) for the specified service in your local cluster": "", - "Gets the kubernetes URL(s) for the specified service in your local cluster. In the case of multiple URLs they will be printed one at a time.": "", - "Gets the logs of the running instance, used for debugging minikube, not user code.": "", - "Gets the status of a local kubernetes cluster": "", + "Found {{.number}} invalid profile(s) !": "找到 {{.number}} 个无效的配置文件!", + "Gets the kubernetes URL(s) for the specified service in your local cluster": "获取本地集群中指定服务的 kubernetes URL", + "Gets the kubernetes URL(s) for the specified service in your local cluster. In the case of multiple URLs they will be printed one at a time.": "获取本地集群中指定服务的 kubernetes URL。如果有多个 URL,他们将一次打印一个", + "Gets the logs of the running instance, used for debugging minikube, not user code.": "获取正在运行的实例日志,用于调试 minikube,不是用户代码", + "Gets the status of a local kubernetes cluster": "获取本地 kubernetes 集群状态", "Gets the status of a local kubernetes cluster.\n\tExit status contains the status of minikube's VM, cluster and kubernetes encoded on it's bits in this order from right to left.\n\tEg: 7 meaning: 1 (for minikube NOK) + 2 (for cluster NOK) + 4 (for kubernetes NOK)": "", "Gets the value of PROPERTY_NAME from the minikube config file": "", "Global Flags": "", From 79efa5452d50b1034c48874fc6c4227ff70f49db Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Thu, 10 Oct 2019 11:26:09 -0700 Subject: [PATCH 20/78] More comprehensive network checks --- cmd/minikube/cmd/start.go | 50 ++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index e2fcdda819..ad4797c786 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -435,8 +435,12 @@ func startMachine(config *cfg.Config) (runner command.Runner, preExists bool, ma exit.WithError("Failed to get machine client", err) } host, preExists = startHost(m, config.MachineConfig) + runner, err = machine.CommandRunner(host) + if err != nil { + exit.WithError("Failed to get command runner", err) + } - ip := validateNetwork(host) + ip := validateNetwork(host, runner) // Bypass proxy for minikube's vm host ip err = proxy.ExcludeIP(ip) if err != nil { @@ -447,10 +451,6 @@ func startMachine(config *cfg.Config) (runner command.Runner, preExists bool, ma if err := saveConfig(config); err != nil { exit.WithError("Failed to save config", err) } - runner, err = machine.CommandRunner(host) - if err != nil { - exit.WithError("Failed to get command runner", err) - } return runner, preExists, m, host } @@ -894,7 +894,7 @@ func startHost(api libmachine.API, mc cfg.MachineConfig) (*host.Host, bool) { } // validateNetwork tries to catch network problems as soon as possible -func validateNetwork(h *host.Host) string { +func validateNetwork(h *host.Host, r command.Runner) string { ip, err := h.Driver.GetIP() if err != nil { exit.WithError("Unable to get VM IP address", err) @@ -918,17 +918,39 @@ func validateNetwork(h *host.Host) string { } } - // none driver should not require ssh or any other open ports - if h.Driver.DriverName() == constants.DriverNone { - return ip + // none driver does not need ssh access + if h.Driver.DriverName() != constants.DriverNone { + sshAddr := fmt.Sprintf("%s:22000", ip) + conn, err := net.Dial("tcp", sshAddr) + if err != nil { + exit.WithCodeT(exit.IO, `minikube is unable to connect to the VM at {{.address}}: {{.error}} + +This is likely due to one of two reasons: + +- VPN or firewall interference +- {{.hypervisor}} network configuration issue + +Suggested workarounds: + +- Disable your local VPN or firewall software +- Configure your local VPN or firewall to allow access to {{ip}} +- Restart or reinstall {{.hypervisor}} +- Use an alternative --vm-driver`, out.V{"error": err, "hypervisor": h.Driver.DriverName(), "ip": ip}) + } + defer conn.Close() } - sshAddr := fmt.Sprintf("%s:22000", ip) - conn, err := net.Dial("tcp", sshAddr) - if err != nil { - exit.WithCodeT(exit.IO, "Unable to contact {{.hypervisor}} \"{{.name}}\" VM: {{.error}}\n\nIf you have a VPN or firewall enabled, try turning it off or configuring it so that it does not capture packets sent to {{.ip}}.\n\nAlso, check the {{.hypervisor}} network preferences and/or reboot your machine", out.V{"name": cfg.GetMachineName(), "error": err, "hypervisor": h.Driver.DriverName()}) + if err := r.Run("nslookup kubernetes.io"); err != nil { + out.WarningT("VM is unable to resolve kubernetes.io: {[.error}}", out.V{"error": err}) + } + + if err := r.Run("nslookup k8s.io 8.8.8.8 || nslookup k8s.io 1.1.1.1 || ping -c1 8.8.8.8"); err != nil { + out.WarningT("VM does not have UDP or ICMP access to the internet: {{.error}}", out.V{"error": err}) + } + + if err := r.Run("env HTTPS_PROXY=%s curl https://k8s.gcr.io/"); err != nil { + out.WarningT("VM is unable to connect to https://k8s.gcr.io/: {{.error}}", out.V{"error": err}) } - defer conn.Close() return ip } From 76471ffda5a4ec9633d36eb5c99ef61dd16850fe Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Thu, 10 Oct 2019 12:14:27 -0700 Subject: [PATCH 21/78] Improve error messages, add container registry check --- cmd/minikube/cmd/start.go | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index ad4797c786..37eb9167ef 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -920,10 +920,10 @@ func validateNetwork(h *host.Host, r command.Runner) string { // none driver does not need ssh access if h.Driver.DriverName() != constants.DriverNone { - sshAddr := fmt.Sprintf("%s:22000", ip) + sshAddr := fmt.Sprintf("%s:22", ip) conn, err := net.Dial("tcp", sshAddr) if err != nil { - exit.WithCodeT(exit.IO, `minikube is unable to connect to the VM at {{.address}}: {{.error}} + exit.WithCodeT(exit.IO, `minikube is unable to connect to the VM: {{.error}} This is likely due to one of two reasons: @@ -933,7 +933,7 @@ This is likely due to one of two reasons: Suggested workarounds: - Disable your local VPN or firewall software -- Configure your local VPN or firewall to allow access to {{ip}} +- Configure your local VPN or firewall to allow access to {{.ip}} - Restart or reinstall {{.hypervisor}} - Use an alternative --vm-driver`, out.V{"error": err, "hypervisor": h.Driver.DriverName(), "ip": ip}) } @@ -941,15 +941,22 @@ Suggested workarounds: } if err := r.Run("nslookup kubernetes.io"); err != nil { - out.WarningT("VM is unable to resolve kubernetes.io: {[.error}}", out.V{"error": err}) + out.WarningT("VM is unable to resolve DNS hosts: {[.error}}", out.V{"error": err}) } + // Try both UDP and ICMP to assert basic external connectivity if err := r.Run("nslookup k8s.io 8.8.8.8 || nslookup k8s.io 1.1.1.1 || ping -c1 8.8.8.8"); err != nil { - out.WarningT("VM does not have UDP or ICMP access to the internet: {{.error}}", out.V{"error": err}) + out.WarningT("VM is unable to directly connect to the internet: {{.error}}", out.V{"error": err}) } - if err := r.Run("env HTTPS_PROXY=%s curl https://k8s.gcr.io/"); err != nil { - out.WarningT("VM is unable to connect to https://k8s.gcr.io/: {{.error}}", out.V{"error": err}) + // Try an HTTPS connection to the + proxy := os.Getenv("HTTPS_PROXY") + opts := "-sS" + if proxy != "" { + opts = fmt.Sprintf("-x %s %s", proxy, opts) + } + if err := r.Run(fmt.Sprintf("curl %s https://k8s.gcr.io/", opts)); err != nil { + out.WarningT("VM is unable to connect to the Kubernetes container registry: {{.error}}", out.V{"error": err}) } return ip } From 268ac04f003c1424ee107ad2556e3574eed5bc4f Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Thu, 10 Oct 2019 12:17:56 -0700 Subject: [PATCH 22/78] Don't try curl with localhost proxies --- cmd/minikube/cmd/start.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index 37eb9167ef..fd35dc5074 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -952,7 +952,7 @@ Suggested workarounds: // Try an HTTPS connection to the proxy := os.Getenv("HTTPS_PROXY") opts := "-sS" - if proxy != "" { + if proxy != "" && !strings.HasPrefix(proxy, "localhost") && !strings.HasPrefix(proxy, "127.0") { opts = fmt.Sprintf("-x %s %s", proxy, opts) } if err := r.Run(fmt.Sprintf("curl %s https://k8s.gcr.io/", opts)); err != nil { From 96edacc0a905c6d9707373937142fff1fed43867 Mon Sep 17 00:00:00 2001 From: RickyRajinder Date: Mon, 7 Oct 2019 20:31:06 -0700 Subject: [PATCH 23/78] Changed command runner Fixed test Print error message Change minikube running check to after check if exists Updates Set and adds test for disabling Fix action for minikube not running Fix import order --- cmd/minikube/cmd/config/disable_test.go | 16 ++++++++++- cmd/minikube/cmd/config/enable_test.go | 16 ++++++++++- cmd/minikube/cmd/config/open.go | 5 +++- cmd/minikube/cmd/config/util.go | 37 ++++++++++++++++--------- cmd/minikube/cmd/config/util_test.go | 18 ++++++------ cmd/minikube/cmd/dashboard.go | 4 ++- cmd/minikube/cmd/service.go | 5 +++- go.mod | 1 + pkg/minikube/cluster/cluster.go | 7 +++-- 9 files changed, 79 insertions(+), 30 deletions(-) diff --git a/cmd/minikube/cmd/config/disable_test.go b/cmd/minikube/cmd/config/disable_test.go index 3141605972..dbde3850c7 100644 --- a/cmd/minikube/cmd/config/disable_test.go +++ b/cmd/minikube/cmd/config/disable_test.go @@ -16,10 +16,24 @@ limitations under the License. package config -import "testing" +import ( + "testing" + + "gotest.tools/assert" + pkgConfig "k8s.io/minikube/pkg/minikube/config" + "k8s.io/minikube/pkg/minikube/localpath" +) func TestDisableUnknownAddon(t *testing.T) { if err := Set("InvalidAddon", "false"); err == nil { t.Fatalf("Disable did not return error for unknown addon") } } + +func TestDisableAddon(t *testing.T) { + if err := Set("dashboard", "false"); err != nil { + t.Fatalf("Disable returned unexpected error: " + err.Error()) + } + config, _ := pkgConfig.ReadConfig(localpath.ConfigFile) + assert.Equal(t, config["dashboard"], false) +} diff --git a/cmd/minikube/cmd/config/enable_test.go b/cmd/minikube/cmd/config/enable_test.go index 007d59516d..28556dc1d8 100644 --- a/cmd/minikube/cmd/config/enable_test.go +++ b/cmd/minikube/cmd/config/enable_test.go @@ -16,10 +16,24 @@ limitations under the License. package config -import "testing" +import ( + "testing" + + "gotest.tools/assert" + pkgConfig "k8s.io/minikube/pkg/minikube/config" + "k8s.io/minikube/pkg/minikube/localpath" +) func TestEnableUnknownAddon(t *testing.T) { if err := Set("InvalidAddon", "false"); err == nil { t.Fatalf("Enable did not return error for unknown addon") } } + +func TestEnableAddon(t *testing.T) { + if err := Set("ingress", "true"); err != nil { + t.Fatalf("Enable returned unexpected error: " + err.Error()) + } + config, _ := pkgConfig.ReadConfig(localpath.ConfigFile) + assert.Equal(t, config["ingress"], true) +} diff --git a/cmd/minikube/cmd/config/open.go b/cmd/minikube/cmd/config/open.go index b8becfbfea..8a852729ce 100644 --- a/cmd/minikube/cmd/config/open.go +++ b/cmd/minikube/cmd/config/open.go @@ -17,6 +17,7 @@ limitations under the License. package config import ( + "os" "text/template" "github.com/spf13/cobra" @@ -62,7 +63,9 @@ var addonsOpenCmd = &cobra.Command{ } defer api.Close() - cluster.EnsureMinikubeRunningOrExit(api, 1) + if !cluster.IsMinikubeRunning(api) { + os.Exit(1) + } addon, ok := assets.Addons[addonName] // validate addon input if !ok { exit.WithCodeT(exit.Data, `addon '{{.name}}' is not a valid addon packaged with minikube. diff --git a/cmd/minikube/cmd/config/util.go b/cmd/minikube/cmd/config/util.go index d103ba36ea..e7e5134e46 100644 --- a/cmd/minikube/cmd/config/util.go +++ b/cmd/minikube/cmd/config/util.go @@ -111,6 +111,18 @@ func EnableOrDisableAddon(name string, val string) error { if err != nil { return errors.Wrapf(err, "parsing bool: %s", name) } + addon := assets.Addons[name] + + // check addon status before enabling/disabling it + alreadySet, err := isAddonAlreadySet(addon, enable) + if err != nil { + out.ErrT(out.Conflict, "{{.error}}", out.V{"error": err}) + return err + } + //if addon is already enabled or disabled, do nothing + if alreadySet { + return nil + } // TODO(r2d4): config package should not reference API, pull this out api, err := machine.NewAPIClient() @@ -118,13 +130,18 @@ func EnableOrDisableAddon(name string, val string) error { return errors.Wrap(err, "machine client") } defer api.Close() - cluster.EnsureMinikubeRunningOrExit(api, 0) - addon := assets.Addons[name] + //if minikube is not running, we return and simply update the value in the addon + //config and rewrite the file + if !cluster.IsMinikubeRunning(api) { + return nil + } + host, err := cluster.CheckIfHostExistsAndLoad(api, config.GetMachineName()) if err != nil { return errors.Wrap(err, "getting host") } + cmd, err := machine.CommandRunner(host) if err != nil { return errors.Wrap(err, "command runner") @@ -139,30 +156,24 @@ func EnableOrDisableAddon(name string, val string) error { return enableOrDisableAddonInternal(addon, cmd, data, enable) } -func isAddonAlreadySet(addon *assets.Addon, enable bool) error { - +func isAddonAlreadySet(addon *assets.Addon, enable bool) (bool, error) { addonStatus, err := addon.IsEnabled() if err != nil { - return errors.Wrap(err, "get the addon status") + return false, errors.Wrap(err, "get the addon status") } if addonStatus && enable { - return fmt.Errorf("addon %s was already enabled", addon.Name()) + return true, nil } else if !addonStatus && !enable { - return fmt.Errorf("addon %s was already disabled", addon.Name()) + return true, nil } - return nil + return false, nil } func enableOrDisableAddonInternal(addon *assets.Addon, cmd command.Runner, data interface{}, enable bool) error { var err error - // check addon status before enabling/disabling it - if err := isAddonAlreadySet(addon, enable); err != nil { - out.ErrT(out.Conflict, "{{.error}}", out.V{"error": err}) - os.Exit(0) - } if enable { for _, addon := range addon.Assets { diff --git a/cmd/minikube/cmd/config/util_test.go b/cmd/minikube/cmd/config/util_test.go index 3cbab76a38..ca1faa86d4 100644 --- a/cmd/minikube/cmd/config/util_test.go +++ b/cmd/minikube/cmd/config/util_test.go @@ -85,15 +85,12 @@ func TestSetBool(t *testing.T) { func TestIsAddonAlreadySet(t *testing.T) { testCases := []struct { addonName string - expectErr string }{ { addonName: "ingress", - expectErr: "addon ingress was already ", }, { addonName: "heapster", - expectErr: "addon heapster was already ", }, } @@ -101,13 +98,16 @@ func TestIsAddonAlreadySet(t *testing.T) { addon := assets.Addons[test.addonName] addonStatus, _ := addon.IsEnabled() - expectMsg := test.expectErr + "enabled" - if !addonStatus { - expectMsg = test.expectErr + "disabled" + alreadySet, err := isAddonAlreadySet(addon, addonStatus) + if !alreadySet { + if addonStatus { + t.Errorf("Did not get expected status, \n\n expected %+v already enabled", test.addonName) + } else { + t.Errorf("Did not get expected status, \n\n expected %+v already disabled", test.addonName) + } } - err := isAddonAlreadySet(addon, addonStatus) - if err.Error() != expectMsg { - t.Errorf("Did not get expected error, \n\n expected: %+v \n\n actual: %+v", expectMsg, err) + if err != nil { + t.Errorf("Got unexpected error: %+v", err) } } } diff --git a/cmd/minikube/cmd/dashboard.go b/cmd/minikube/cmd/dashboard.go index 4908e319f1..27a472d80b 100644 --- a/cmd/minikube/cmd/dashboard.go +++ b/cmd/minikube/cmd/dashboard.go @@ -93,7 +93,9 @@ var dashboardCmd = &cobra.Command{ exit.WithCodeT(exit.NoInput, "kubectl not found in PATH, but is required for the dashboard. Installation guide: https://kubernetes.io/docs/tasks/tools/install-kubectl/") } - cluster.EnsureMinikubeRunningOrExit(api, 1) + if !cluster.IsMinikubeRunning(api) { + os.Exit(1) + } // Check dashboard status before enabling it dashboardAddon := assets.Addons["dashboard"] diff --git a/cmd/minikube/cmd/service.go b/cmd/minikube/cmd/service.go index d550c736a7..d0068a23da 100644 --- a/cmd/minikube/cmd/service.go +++ b/cmd/minikube/cmd/service.go @@ -17,6 +17,7 @@ limitations under the License. package cmd import ( + "os" "text/template" "github.com/spf13/cobra" @@ -64,7 +65,9 @@ var serviceCmd = &cobra.Command{ } defer api.Close() - cluster.EnsureMinikubeRunningOrExit(api, 1) + if !cluster.IsMinikubeRunning(api) { + os.Exit(1) + } err = service.WaitAndMaybeOpenService(api, namespace, svc, serviceURLTemplate, serviceURLMode, https, wait, interval) if err != nil { diff --git a/go.mod b/go.mod index 80bd0d2055..77e516b0be 100644 --- a/go.mod +++ b/go.mod @@ -76,6 +76,7 @@ require ( gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect + gotest.tools v2.2.0+incompatible k8s.io/api v0.0.0 k8s.io/apimachinery v0.0.0 k8s.io/client-go v0.0.0 diff --git a/pkg/minikube/cluster/cluster.go b/pkg/minikube/cluster/cluster.go index 96f8e45b7a..84e43632fa 100644 --- a/pkg/minikube/cluster/cluster.go +++ b/pkg/minikube/cluster/cluster.go @@ -604,12 +604,13 @@ func CreateSSHShell(api libmachine.API, args []string) error { // EnsureMinikubeRunningOrExit checks that minikube has a status available and that // the status is `Running`, otherwise it will exit -func EnsureMinikubeRunningOrExit(api libmachine.API, exitStatus int) { +func IsMinikubeRunning(api libmachine.API) bool { s, err := GetHostStatus(api) if err != nil { - exit.WithError("Error getting machine status", err) + return false } if s != state.Running.String() { - exit.WithCodeT(exit.Unavailable, "minikube is not running, so the service cannot be accessed") + return false } + return true } From 9bf904141c3636810bfb1abffd9f3675108b3f9b Mon Sep 17 00:00:00 2001 From: Nanik T Date: Fri, 11 Oct 2019 23:46:02 +1100 Subject: [PATCH 24/78] Warn if incompatible kubectl version is in use Fixes: #3329 Modification is done inside start.go where additional checking on the version returned via the kubectl CLI is checked. Running 'kubectl version --output=json' will return both client and server information. --- cmd/minikube/cmd/start.go | 61 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index 21b522eddb..d025635c00 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -17,6 +17,7 @@ limitations under the License. package cmd import ( + "encoding/json" "fmt" "net" "net/url" @@ -130,6 +131,17 @@ var ( extraOptions cfg.ExtraOptionSlice ) +type kubectlversion struct { + CVersion ClientVersion `json:"clientVersion"` + SVersion ClientVersion `json:"serverVersion"` +} + +type ClientVersion struct { + Major string `json:"major"` + Minor string `json:"minor"` + GitVersion string `json:"gitVersion"` +} + func init() { initMinikubeFlags() initKubernetesFlags() @@ -477,16 +489,57 @@ func showVersionInfo(k8sVersion string, cr cruntime.Manager) { } } +/** +Function to check for kubectl. The checking is to compare +the version reported by both the client and server. It is +that kubectl will be of the same version or 1 lower than +the kubernetes version. +*/ func showKubectlConnectInfo(kcs *kubeconfig.Settings) { + var output []byte + clientVersion := kubectlversion{} + serverVersion := kubectlversion{} + + path, err := exec.LookPath("kubectl") + + if err != nil { + out.T(out.Tip, "For best results, install kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/") + } else { + glog.Infof("Kubectl found at the following location %s. Let's execute and get the result", path) + output, err = exec.Command(path, "version", "--output=json").Output() + + // ...once we get something back do some version checking + if err == nil { + glog.Infof("Received output from kubectl %s", output) + + // unmarshal both the {client} + clientjsonErr := json.Unmarshal(output, &clientVersion) + + // ....... and {server} json + serverjsonErr := json.Unmarshal(output, &serverVersion) + + if (clientjsonErr != nil) || (serverjsonErr != nil) { + glog.Infof("There was an error processing the json output") + } else { + // obtain the minor version for both + serverMinor, _ := strconv.Atoi(serverVersion.SVersion.Minor) + clientMinor, _ := strconv.Atoi(serverVersion.CVersion.Minor) + + if clientMinor < serverMinor { + out.T(out.Tip, "The version of kubectl {{.kubectl}} installed is incompatible with your Kubernetes {{.kubernetes}} deployment. Please upgrade/downgrade as necessary, or use minikube kubectlto connect to your cluster", + out.V{"kubectl": clientVersion.CVersion.GitVersion, "kubernetes": serverVersion.SVersion.GitVersion}) + } + } + } else { + out.T(out.Tip, "For best results, install kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/") + } + } + if kcs.KeepContext { out.T(out.Kubectl, "To connect to this cluster, use: kubectl --context={{.name}}", out.V{"name": kcs.ClusterName}) } else { out.T(out.Ready, `Done! kubectl is now configured to use "{{.name}}"`, out.V{"name": cfg.GetMachineName()}) } - _, err := exec.LookPath("kubectl") - if err != nil { - out.T(out.Tip, "For best results, install kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/") - } } func selectDriver(oldConfig *cfg.Config) string { From f39ecda4cb1d589a22d03e1cbaff946d411351bc Mon Sep 17 00:00:00 2001 From: Josh Woodcock Date: Fri, 11 Oct 2019 09:43:00 -0500 Subject: [PATCH 25/78] Add tests for addons custom output format --- cmd/minikube/cmd/config/addons_list.go | 6 +++- test/integration/functional_test.go | 48 ++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/cmd/minikube/cmd/config/addons_list.go b/cmd/minikube/cmd/config/addons_list.go index ddc207ae08..3a3b50ac05 100644 --- a/cmd/minikube/cmd/config/addons_list.go +++ b/cmd/minikube/cmd/config/addons_list.go @@ -52,7 +52,11 @@ var addonsListCmd = &cobra.Command{ } func init() { - addonsListCmd.Flags().StringVar(&addonListFormat, "format", defaultAddonListFormat, + addonsListCmd.Flags().StringVarP( + &addonListFormat, + "format", + "f", + defaultAddonListFormat, `Go template format string for the addon list output. The format for Go templates can be found here: https://golang.org/pkg/text/template/ For the list of accessible variables for the template, see the struct values here: https://godoc.org/k8s.io/minikube/cmd/minikube/cmd/config#AddonListTemplate`) AddonsCmd.AddCommand(addonsListCmd) diff --git a/test/integration/functional_test.go b/test/integration/functional_test.go index 69a8864e93..7db6a99411 100644 --- a/test/integration/functional_test.go +++ b/test/integration/functional_test.go @@ -29,6 +29,7 @@ import ( "os" "os/exec" "path/filepath" + "regexp" "strings" "testing" "time" @@ -87,6 +88,7 @@ func TestFunctional(t *testing.T) { {"MountCmd", validateMountCmd}, {"ProfileCmd", validateProfileCmd}, {"ServicesCmd", validateServicesCmd}, + {"AddonsCmd", validateAddonsCmd}, {"PersistentVolumeClaim", validatePersistentVolumeClaim}, {"TunnelCmd", validateTunnelCmd}, {"SSHCmd", validateSSHCmd}, @@ -314,6 +316,52 @@ func validateServicesCmd(ctx context.Context, t *testing.T, profile string) { } } +// validateAddonsCmd asserts basic "addon" command functionality +func validateAddonsCmd(ctx context.Context, t *testing.T, profile string) { + + // Default output + rr, err := Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "addons", "list")) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } + listLines := strings.Split(strings.TrimSpace(rr.Stdout.String()), "\n") + r := regexp.MustCompile(`-\s[a-z|-]+:\s(enabled|disabled)`) + for _, line := range listLines { + match := r.MatchString(line) + if !match { + t.Errorf("Plugin output did not match expected format. Got: %s", line) + } + } + + // Custom format + rr, err = Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "addons", "list", "--format", `"{{.AddonName}}":"{{.AddonStatus}}"`)) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } + listLines = strings.Split(strings.TrimSpace(rr.Stdout.String()), "\n") + r = regexp.MustCompile(`"[a-z|-]+":"(enabled|disabled)"`) + for _, line := range listLines { + match := r.MatchString(line) + if !match { + t.Errorf("Plugin output did not match expected custom format. Got: %s", line) + } + } + + // Custom format shorthand + rr, err = Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "addons", "list", "-f", `"{{.AddonName}}":"{{.AddonStatus}}"`)) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } + listLines = strings.Split(strings.TrimSpace(rr.Stdout.String()), "\n") + r = regexp.MustCompile(`"[a-z|-]+":"(enabled|disabled)"`) + for _, line := range listLines { + match := r.MatchString(line) + if !match { + t.Errorf("Plugin output did not match expected custom format. Got: %s", line) + } + } +} + // validateSSHCmd asserts basic "ssh" command functionality func validateSSHCmd(ctx context.Context, t *testing.T, profile string) { if NoneDriver() { From b237471a172c17c323c53802e00a1f00b848e684 Mon Sep 17 00:00:00 2001 From: Marcin Niemira Date: Sat, 12 Oct 2019 12:25:53 +1100 Subject: [PATCH 26/78] add some tests to translate pkg --- pkg/minikube/translate/translate_test.go | 50 ++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/pkg/minikube/translate/translate_test.go b/pkg/minikube/translate/translate_test.go index 00c4411810..fd7a73cf64 100644 --- a/pkg/minikube/translate/translate_test.go +++ b/pkg/minikube/translate/translate_test.go @@ -51,3 +51,53 @@ func TestSetPreferredLanguage(t *testing.T) { } } + +func TestT(t *testing.T) { + var tests = []struct { + description, input, expected string + langDef, langPref language.Tag + translations map[string]interface{} + }{ + { + description: "empty string not default language", + input: "", + expected: "", + langPref: language.English, + langDef: language.Lithuanian, + }, + { + description: "empty string and default language", + input: "", + expected: "", + langPref: language.English, + langDef: language.English, + }, + { + description: "existing translation", + input: "cat", + expected: "kot", + langPref: language.Lithuanian, + langDef: language.English, + translations: map[string]interface{}{"cat": "kot"}, + }, + { + description: "not existing translation", + input: "cat", + expected: "cat", + langPref: language.Lithuanian, + langDef: language.English, + translations: map[string]interface{}{"dog": "pies"}, + }, + } + for _, test := range tests { + t.Run(test.description, func(t *testing.T) { + defaultLanguage = test.langDef + preferredLanguage = test.langPref + Translations = test.translations + got := T(test.input) + if test.expected != got { + t.Errorf("T(%v) shoud return %v, but got: %v", test.input, test.expected, got) + } + }) + } +} From 3dff822e8bd956b92d008096273d393e91e08f40 Mon Sep 17 00:00:00 2001 From: Marcin Niemira Date: Sat, 12 Oct 2019 12:43:59 +1100 Subject: [PATCH 27/78] remove single test due to discussion on GH --- pkg/minikube/machine/cache_binaries_test.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pkg/minikube/machine/cache_binaries_test.go b/pkg/minikube/machine/cache_binaries_test.go index b522de6976..6ccaf2e3f7 100644 --- a/pkg/minikube/machine/cache_binaries_test.go +++ b/pkg/minikube/machine/cache_binaries_test.go @@ -128,11 +128,6 @@ func TestCacheBinary(t *testing.T) { t.Fatalf("error (%v) during changing permissions of dir %v", err, noWritePermDir) } - // noPermsDir is directory owned by root. Regular user is not able to write to it. - noPermsDir := "/etc" - if runtime.GOOS == "windows" { - noPermsDir = "C:\\Windows\\System32" - } var tc = []struct { desc, version, osName, archName string minikubeHome, binary, description string @@ -147,15 +142,6 @@ func TestCacheBinary(t *testing.T) { err: false, minikubeHome: minikubeHome, }, - { - desc: "minikube home is pointing to dir without perms", - version: "v1.16.0", - osName: runtime.GOOS, - archName: "arm", - binary: "kubectl", - err: true, - minikubeHome: noPermsDir, - }, { desc: "minikube home in dir without perms and arm runtime", version: "v1.16.0", From 8bf56f0d6cd0e458fb6b6e6448cb0c97d00661dd Mon Sep 17 00:00:00 2001 From: Alexandre Fiori Date: Sun, 13 Oct 2019 18:57:17 +0100 Subject: [PATCH 28/78] Add docs for using registry on macOS --- .../en/docs/Tasks/Registry/insecure.md | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/site/content/en/docs/Tasks/Registry/insecure.md b/site/content/en/docs/Tasks/Registry/insecure.md index aceba59e66..0ccf967899 100644 --- a/site/content/en/docs/Tasks/Registry/insecure.md +++ b/site/content/en/docs/Tasks/Registry/insecure.md @@ -15,3 +15,30 @@ You can use the `--insecure-registry` flag on the One nifty hack is to allow the kubelet running in minikube to talk to registries deployed inside a pod in the cluster without backing them with TLS certificates. Because the default service cluster IP is known to be available at 10.0.0.1, users can pull images from registries deployed inside the cluster by creating the cluster with `minikube start --insecure-registry "10.0.0.0/24"`. + +### docker on macOS + +Quick guide for configuring minikube and docker on macOS, enabling docker to push images to minikube's registry. + +The first step is to enable the registry addon: + +``` +minikube addons enable registry +``` + +When enabled, the registry addon exposes its port 5000 on the minikube's virtual machine. + +In order to make docker accept pushing images to this registry, we have to redirect port 5000 on the docker virtual machine over to port 5000 on the minikube machine. We can (ab)use docker's network configuration to instantiate a container on the docker's host, and run socat there: + +``` +docker run --rm -it --network=host alpine ash -c "apk add socat && socat TCP-LISTEN:5000,reuseaddr,fork TCP:$(minikube ip):5000" +``` + +Once socat is running it's possible to push images to the minikube registry: + +``` +docker tag my/image localhost:5000/myimage +docker push localhost:5000/myimage +``` + +After the image is pushed, refer to it by `localhost:5000/{name}` in kubectl specs. From fd105d03f0a4dd644805921bb01fdd0fdb92bfd8 Mon Sep 17 00:00:00 2001 From: vishakha <54327666+vishakhanihore@users.noreply.github.com> Date: Mon, 14 Oct 2019 18:44:07 +0530 Subject: [PATCH 29/78] Rendering links --- site/layouts/partials/community-links.html | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/site/layouts/partials/community-links.html b/site/layouts/partials/community-links.html index 9c5545d4dc..be51d13066 100644 --- a/site/layouts/partials/community-links.html +++ b/site/layouts/partials/community-links.html @@ -7,12 +7,18 @@ {{ with index $links "user"}} {{ template "community-links-list" . }} {{ end }} +{{ with index $links "mailinglistuser"}} +{{ template "community-links-list" . }} +{{ end }}

Develop and Contribute

If you want to get more involved by contributing to {{ .Site.Title }}, join us here: {{ with index $links "developer"}} {{ template "community-links-list" . }} +{{ end }} + {{ with index $links "mailinglistdev"}} +{{ template "community-links-list" . }} {{ end }}

You can find out how to contribute to these docs in our Contributing Guide.

From 4c2e2700990c9d0022b385348b91cdce83c795bf Mon Sep 17 00:00:00 2001 From: vishakha <54327666+vishakhanihore@users.noreply.github.com> Date: Mon, 14 Oct 2019 18:44:12 +0530 Subject: [PATCH 30/78] Addition of links for the community --- site/config.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/site/config.toml b/site/config.toml index 85c597f291..d574e1eee3 100644 --- a/site/config.toml +++ b/site/config.toml @@ -115,6 +115,11 @@ no = 'Sorry to hear that. Please Date: Mon, 14 Oct 2019 20:15:07 +0530 Subject: [PATCH 31/78] Changing `Mini-Kube` to `minikube` --- site/config.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/config.toml b/site/config.toml index d574e1eee3..d35a54a6b7 100644 --- a/site/config.toml +++ b/site/config.toml @@ -119,7 +119,7 @@ no = 'Sorry to hear that. Please Date: Mon, 14 Oct 2019 22:02:27 +0530 Subject: [PATCH 32/78] Fix the rendering issue --- site/config.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/site/config.toml b/site/config.toml index d35a54a6b7..e49df4aedd 100644 --- a/site/config.toml +++ b/site/config.toml @@ -115,10 +115,10 @@ no = 'Sorry to hear that. Please Date: Mon, 14 Oct 2019 22:03:03 +0530 Subject: [PATCH 33/78] Removing un-used code --- site/layouts/partials/community-links.html | 6 ------ 1 file changed, 6 deletions(-) diff --git a/site/layouts/partials/community-links.html b/site/layouts/partials/community-links.html index be51d13066..9c5545d4dc 100644 --- a/site/layouts/partials/community-links.html +++ b/site/layouts/partials/community-links.html @@ -7,18 +7,12 @@ {{ with index $links "user"}} {{ template "community-links-list" . }} {{ end }} -{{ with index $links "mailinglistuser"}} -{{ template "community-links-list" . }} -{{ end }} From 7ef46540874e636a09bc3f07f4f3d620aebb05bf Mon Sep 17 00:00:00 2001 From: Cornelius Weig Date: Mon, 14 Oct 2019 23:16:01 +0200 Subject: [PATCH 34/78] Delegate release notes to external tool --- hack/.gitignore | 1 + hack/release_notes.sh | 18 ++++- hack/release_notes/listpullreqs.go | 109 ----------------------------- 3 files changed, 18 insertions(+), 110 deletions(-) create mode 100644 hack/.gitignore delete mode 100644 hack/release_notes/listpullreqs.go diff --git a/hack/.gitignore b/hack/.gitignore new file mode 100644 index 0000000000..6168f032c4 --- /dev/null +++ b/hack/.gitignore @@ -0,0 +1 @@ +release-notes diff --git a/hack/release_notes.sh b/hack/release_notes.sh index 0cc0733243..ca0acc9fc4 100755 --- a/hack/release_notes.sh +++ b/hack/release_notes.sh @@ -18,7 +18,23 @@ set -eux -o pipefail DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -go run "${DIR}/release_notes/listpullreqs.go" +install_release_notes_helper() { + release_notes_workdir="$(mktemp -d)" + trap 'rm -rf -- ${release_notes_workdir}' RETURN + + # See https://stackoverflow.com/questions/56842385/using-go-get-to-download-binaries-without-adding-them-to-go-mod for this workaround + cd "${release_notes_workdir}" + go mod init release-notes + GOBIN="$DIR" go get github.com/corneliusweig/release-notes + cd - +} + +if ! [[ -x "${DIR}/release-notes" ]]; then + echo >&2 'Installing release-notes' + install_release_notes_helper +fi + +"${DIR}/release-notes" kubernetes minikube echo "Huge thank you for this release towards our contributors: " git log "$(git describe --abbrev=0)".. --format="%aN" --reverse | sort | uniq | awk '{printf "- %s\n", $0 }' diff --git a/hack/release_notes/listpullreqs.go b/hack/release_notes/listpullreqs.go deleted file mode 100644 index 64ea8fc3d9..0000000000 --- a/hack/release_notes/listpullreqs.go +++ /dev/null @@ -1,109 +0,0 @@ -/* -Copyright 2018 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. -*/ - -// listpullreqs.go lists pull requests since the last release. -package main - -import ( - "context" - "fmt" - - "github.com/golang/glog" - "github.com/google/go-github/v25/github" - "github.com/spf13/cobra" - "golang.org/x/oauth2" -) - -var ( - token string - fromTag string - toTag string -) - -var rootCmd = &cobra.Command{ - Use: "listpullreqs fromTag toTag", - Short: "Lists pull requests between two versions in our changelog markdown format", - ArgAliases: []string{"fromTag", "toTag"}, - Run: func(cmd *cobra.Command, args []string) { - printPullRequests() - }, -} - -const org = "kubernetes" -const repo = "minikube" - -func main() { - rootCmd.Flags().StringVar(&token, "token", "", "Specify personal Github Token if you are hitting a rate limit anonymously. https://github.com/settings/tokens") - rootCmd.Flags().StringVar(&fromTag, "fromTag", "", "comparison of commits is based on this tag (defaults to the latest tag in the repo)") - rootCmd.Flags().StringVar(&toTag, "toTag", "master", "this is the commit that is compared with fromTag") - if err := rootCmd.Execute(); err != nil { - glog.Fatalf("Failed to execute: %v", err) - } -} - -func printPullRequests() { - client := getClient() - - releases, _, err := client.Repositories.ListReleases(context.Background(), org, repo, &github.ListOptions{}) - if err != nil { - glog.Fatalf("Failed to list releases: %v", err) - } - lastReleaseTime := *releases[0].PublishedAt - fmt.Println(fmt.Sprintf("Collecting pull request that were merged since the last release: %s (%s)", *releases[0].TagName, lastReleaseTime)) - - listSize := 1 - for page := 1; listSize > 0; page++ { - pullRequests, _, err := client.PullRequests.List(context.Background(), org, repo, &github.PullRequestListOptions{ - State: "closed", - Sort: "updated", - Direction: "desc", - ListOptions: github.ListOptions{ - PerPage: 100, - Page: page, - }, - }) - if err != nil { - glog.Fatalf("Failed to list pull requests: %v", err) - } - - seen := 0 - for idx := range pullRequests { - pr := pullRequests[idx] - if pr.MergedAt != nil { - if pr.GetMergedAt().After(lastReleaseTime.Time) { - fmt.Printf("* %s [#%d](https://github.com/%s/%s/pull/%d)\n", pr.GetTitle(), *pr.Number, org, repo, *pr.Number) - seen++ - } - } - } - if seen == 0 { - break - } - listSize = len(pullRequests) - } -} - -func getClient() *github.Client { - if len(token) == 0 { - return github.NewClient(nil) - } - ctx := context.Background() - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: token}, - ) - tc := oauth2.NewClient(ctx, ts) - return github.NewClient(tc) -} From d2557e688c54e9b38b3450f173e32fe82d88b191 Mon Sep 17 00:00:00 2001 From: Kenta Iso Date: Tue, 15 Oct 2019 22:41:59 +0900 Subject: [PATCH 35/78] fix kubeconfig.UpdateIP() argument order --- cmd/minikube/cmd/update-context.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/minikube/cmd/update-context.go b/cmd/minikube/cmd/update-context.go index 3a6eeda815..9474bf7ab5 100644 --- a/cmd/minikube/cmd/update-context.go +++ b/cmd/minikube/cmd/update-context.go @@ -44,7 +44,7 @@ var updateContextCmd = &cobra.Command{ if err != nil { exit.WithError("Error host driver ip status", err) } - updated, err := kubeconfig.UpdateIP(ip, constants.KubeconfigPath, machineName) + updated, err := kubeconfig.UpdateIP(ip, machineName, constants.KubeconfigPath) if err != nil { exit.WithError("update config", err) } From d2f987adffca6b14087a3ce1eea50b21699fa9e1 Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Wed, 16 Oct 2019 10:53:14 -0700 Subject: [PATCH 36/78] Speed up RNG initialization on hyperkit --- pkg/minikube/drivers/hyperkit/driver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/minikube/drivers/hyperkit/driver.go b/pkg/minikube/drivers/hyperkit/driver.go index 0db642f25b..fe44da80ea 100644 --- a/pkg/minikube/drivers/hyperkit/driver.go +++ b/pkg/minikube/drivers/hyperkit/driver.go @@ -61,6 +61,6 @@ func createHyperkitHost(config cfg.MachineConfig) interface{} { UUID: uuID, VpnKitSock: config.HyperkitVpnKitSock, VSockPorts: config.HyperkitVSockPorts, - Cmdline: "loglevel=3 user=docker console=ttyS0 console=tty0 noembed nomodeset norestore waitusb=10 systemd.legacy_systemd_cgroup_controller=yes base host=" + cfg.GetMachineName(), + Cmdline: "loglevel=3 console=ttyS0 console=tty0 noembed nomodeset norestore waitusb=10 systemd.legacy_systemd_cgroup_controller=yes random.trust_cpu=on hw_rng_model=virtio base host=" + cfg.GetMachineName(), } } From ed20dec45661a6ce7da2f3090d9348b101a5d18c Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Wed, 16 Oct 2019 10:59:01 -0700 Subject: [PATCH 37/78] Propagate hyperkit changes to main ISO --- deploy/iso/minikube-iso/board/coreos/minikube/isolinux.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/iso/minikube-iso/board/coreos/minikube/isolinux.cfg b/deploy/iso/minikube-iso/board/coreos/minikube/isolinux.cfg index ecb2f1d708..9857e0bb2a 100644 --- a/deploy/iso/minikube-iso/board/coreos/minikube/isolinux.cfg +++ b/deploy/iso/minikube-iso/board/coreos/minikube/isolinux.cfg @@ -2,4 +2,4 @@ default 1 label 1 kernel /boot/bzImage initrd /boot/initrd - append root=/dev/sr0 loglevel=3 console=ttyS0 noembed nomodeset norestore waitusb=10 systemd.legacy_systemd_cgroup_controller=yes + append root=/dev/sr0 loglevel=3 console=ttyS0 noembed nomodeset norestore waitusb=10 random.trust_cpu=on hw_rng_model=virtio systemd.legacy_systemd_cgroup_controller=yes From 8ca74ef186c324fdfdcbf4999ba38d070b97a956 Mon Sep 17 00:00:00 2001 From: tstromberg Date: Wed, 16 Oct 2019 13:38:47 -0700 Subject: [PATCH 38/78] Use the value of --image-repository for connectivity check --- cmd/minikube/cmd/start.go | 11 ++++++++--- pkg/minikube/bootstrapper/images/images.go | 9 +++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index 94c5bb9d90..9851a9fc0e 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -764,7 +764,7 @@ func generateCfgFromFlags(cmd *cobra.Command, k8sVersion string, driver string) repository = autoSelectedRepository } - if repository != "" { + if cmd.Flags().Changed(imageRepository) { out.T(out.SuccessType, "Using image repository {{.name}}", out.V{"name": repository}) } @@ -966,8 +966,13 @@ Suggested workarounds: if proxy != "" && !strings.HasPrefix(proxy, "localhost") && !strings.HasPrefix(proxy, "127.0") { opts = fmt.Sprintf("-x %s %s", proxy, opts) } - if err := r.Run(fmt.Sprintf("curl %s https://k8s.gcr.io/", opts)); err != nil { - out.WarningT("VM is unable to connect to the Kubernetes container registry: {{.error}}", out.V{"error": err}) + + repo := viper.GetString(imageRepository) + if repo == "" { + repo = images.DefaultImageRepo + } + if err := r.Run(fmt.Sprintf("curl %s https://%s/", opts, repo)); err != nil { + out.WarningT("VM is unable to connect to the selected image repository: {{.error}}", out.V{"error": err}) } return ip } diff --git a/pkg/minikube/bootstrapper/images/images.go b/pkg/minikube/bootstrapper/images/images.go index 8d4d723ca8..a8bc2b13e0 100644 --- a/pkg/minikube/bootstrapper/images/images.go +++ b/pkg/minikube/bootstrapper/images/images.go @@ -25,10 +25,15 @@ import ( minikubeVersion "k8s.io/minikube/pkg/version" ) +const ( + DefaultImageRepo = "k8s.gcr.io" + DefaultMinikubeRepo = "gcr.io/k8s-minikube" +) + // getImageRepositories returns either the k8s image registry on GCR or a mirror if specified func getImageRepository(imageRepository string) string { if imageRepository == "" { - imageRepository = "k8s.gcr.io" + imageRepository = DefaultImageRepo } if !strings.HasSuffix(imageRepository, "/") { imageRepository += "/" @@ -41,7 +46,7 @@ func getImageRepository(imageRepository string) string { func getMinikubeRepository(imageRepository string) string { minikubeRepository := imageRepository if minikubeRepository == "" { - minikubeRepository = "gcr.io/k8s-minikube" + minikubeRepository = DefaultMinikubeRepo } if !strings.HasSuffix(minikubeRepository, "/") { minikubeRepository += "/" From a6d7989bfc195cb4c77aa34accb557c7ddfa70dd Mon Sep 17 00:00:00 2001 From: Sharif Elgamal Date: Wed, 16 Oct 2019 14:51:13 -0700 Subject: [PATCH 39/78] add ability to override autoupdating drivers --- Makefile | 2 +- cmd/minikube/cmd/start.go | 21 +++++++++------------ pkg/drivers/drivers.go | 10 ++++++++-- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index f4efa1dfdb..87639123db 100755 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ # Bump these on release - and please check ISO_VERSION for correctness. VERSION_MAJOR ?= 1 VERSION_MINOR ?= 4 -VERSION_BUILD ?= 1 +VERSION_BUILD ?= 0 RAW_VERSION=$(VERSION_MAJOR).$(VERSION_MINOR).${VERSION_BUILD} VERSION ?= v$(RAW_VERSION) diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index 21b522eddb..35175cc602 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -117,6 +117,7 @@ const ( minimumMemorySize = "1024mb" minimumCPUS = 2 minimumDiskSize = "2000mb" + autoUpdate = "auto-update-drivers" ) var ( @@ -170,6 +171,7 @@ func initMinikubeFlags() { startCmd.Flags().Bool(waitUntilHealthy, true, "Wait until Kubernetes core services are healthy before exiting.") startCmd.Flags().Duration(waitTimeout, 6*time.Minute, "max time to wait per Kubernetes core services to be healthy.") startCmd.Flags().Bool(nativeSSH, true, "Use native Golang SSH client (default true). Set to 'false' to use the command line 'ssh' command when accessing the docker machine. Useful for the machine drivers when they will not start with 'Waiting for SSH'.") + startCmd.Flags().Bool(autoUpdate, true, "If set, automatically updates drivers to the latest version. Defaults to true.") } // initKubernetesFlags inits the commandline flags for kubernetes related options @@ -293,7 +295,13 @@ func runStart(cmd *cobra.Command, args []string) { validateFlags(driver) validateUser(driver) - _ = getMinikubeVersion(driver) + v, err := version.GetSemverVersion() + if err != nil { + out.WarningT("Error parsing minikube version: {{.error}}", out.V{"error": err}) + } else if err := drivers.InstallOrUpdate(driver, localpath.MakeMiniPath("bin"), v, viper.GetBool(interactive), viper.GetBool(autoUpdate)); err != nil { + out.WarningT("Unable to update {{.driver}} driver: {{.error}}", out.V{"driver": driver, "error": err}) + } + k8sVersion, isUpgrade := getKubernetesVersion(oldConfig) config, err := generateCfgFromFlags(cmd, k8sVersion, driver) if err != nil { @@ -933,17 +941,6 @@ func validateNetwork(h *host.Host) string { return ip } -// getMinikubeVersion ensures that the driver binary is up to date -func getMinikubeVersion(driver string) string { - v, err := version.GetSemverVersion() - if err != nil { - out.WarningT("Error parsing minikube version: {{.error}}", out.V{"error": err}) - } else if err := drivers.InstallOrUpdate(driver, localpath.MakeMiniPath("bin"), v, viper.GetBool(interactive)); err != nil { - out.WarningT("Unable to update {{.driver}} driver: {{.error}}", out.V{"driver": driver, "error": err}) - } - return v.String() -} - // getKubernetesVersion ensures that the requested version is reasonable func getKubernetesVersion(old *cfg.Config) (string, bool) { rawVersion := viper.GetString(kubernetesVersion) diff --git a/pkg/drivers/drivers.go b/pkg/drivers/drivers.go index da7edaf2d8..1a18a2a8eb 100644 --- a/pkg/drivers/drivers.go +++ b/pkg/drivers/drivers.go @@ -149,14 +149,15 @@ func fixMachinePermissions(path string) error { } // InstallOrUpdate downloads driver if it is not present, or updates it if there's a newer version -func InstallOrUpdate(driver string, directory string, v semver.Version, interactive bool) error { +func InstallOrUpdate(driver string, directory string, v semver.Version, interactive bool, autoUpdate bool) error { if driver != constants.DriverKvm2 && driver != constants.DriverHyperkit { return nil } executable := fmt.Sprintf("docker-machine-driver-%s", driver) + exists := driverExists(executable) path, err := validateDriver(executable, v) - if err != nil { + if !exists || (err != nil && autoUpdate) { glog.Warningf("%s: %v", executable, err) path = filepath.Join(directory, executable) derr := download(executable, path, v) @@ -240,6 +241,11 @@ func validateDriver(driver string, v semver.Version) (string, error) { return path, nil } +func driverExists(driver string) bool { + _, err := exec.LookPath(driver) + return err == nil +} + func driverWithChecksumURL(driver string, v semver.Version) string { base := fmt.Sprintf("https://github.com/kubernetes/minikube/releases/download/v%s/%s", v, driver) return fmt.Sprintf("%s?checksum=file:%s.sha256", base, base) From 008991fa27d237f70cbd0e6c15e54da52042e27e Mon Sep 17 00:00:00 2001 From: Sharif Elgamal Date: Wed, 16 Oct 2019 14:51:39 -0700 Subject: [PATCH 40/78] undo makefile change --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 87639123db..f4efa1dfdb 100755 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ # Bump these on release - and please check ISO_VERSION for correctness. VERSION_MAJOR ?= 1 VERSION_MINOR ?= 4 -VERSION_BUILD ?= 0 +VERSION_BUILD ?= 1 RAW_VERSION=$(VERSION_MAJOR).$(VERSION_MINOR).${VERSION_BUILD} VERSION ?= v$(RAW_VERSION) From 0bca92a3effa4868ee6785c8f0052564fee37d54 Mon Sep 17 00:00:00 2001 From: Sharif Elgamal Date: Wed, 16 Oct 2019 15:01:26 -0700 Subject: [PATCH 41/78] fix tests --- test/integration/driver_install_or_update_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/driver_install_or_update_test.go b/test/integration/driver_install_or_update_test.go index de11940873..99eeed886e 100644 --- a/test/integration/driver_install_or_update_test.go +++ b/test/integration/driver_install_or_update_test.go @@ -84,7 +84,7 @@ func TestKVMDriverInstallOrUpdate(t *testing.T) { t.Fatalf("Expected new semver. test: %v, got: %v", tc.name, err) } - err = drivers.InstallOrUpdate("kvm2", dir, newerVersion, true) + err = drivers.InstallOrUpdate("kvm2", dir, newerVersion, true, true) if err != nil { t.Fatalf("Failed to update driver to %v. test: %s, got: %v", newerVersion, tc.name, err) } @@ -147,7 +147,7 @@ func TestHyperKitDriverInstallOrUpdate(t *testing.T) { t.Fatalf("Expected new semver. test: %v, got: %v", tc.name, err) } - err = drivers.InstallOrUpdate("hyperkit", dir, newerVersion, true) + err = drivers.InstallOrUpdate("hyperkit", dir, newerVersion, true, true) if err != nil { t.Fatalf("Failed to update driver to %v. test: %s, got: %v", newerVersion, tc.name, err) } From 5c1647f6e7daf46d5ee88fcb19090b79672ae438 Mon Sep 17 00:00:00 2001 From: tstromberg Date: Wed, 16 Oct 2019 16:00:13 -0700 Subject: [PATCH 42/78] Use more stable gluster mirror? --- deploy/iso/minikube-iso/package/gluster/gluster.mk | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/deploy/iso/minikube-iso/package/gluster/gluster.mk b/deploy/iso/minikube-iso/package/gluster/gluster.mk index aedf078124..c2d73f1853 100644 --- a/deploy/iso/minikube-iso/package/gluster/gluster.mk +++ b/deploy/iso/minikube-iso/package/gluster/gluster.mk @@ -5,7 +5,10 @@ ################################################################################ GLUSTER_VERSION = 4.1.5 -GLUSTER_SITE = https://download.gluster.org/pub/gluster/glusterfs/4.1/$(GLUSTER_VERSION) +# Official gluster site has SSL problems +# https://bugzilla.redhat.com/show_bug.cgi?id=1572944 +# GLUSTER_SITE = https://download.gluster.org/pub/gluster/glusterfs/4.1/$(GLUSTER_VERSION) +GLUSTER_SITE = http://download.openpkg.org/components/cache/glusterfs/ GLUSTER_SOURCE = glusterfs-$(GLUSTER_VERSION).tar.gz GLUSTER_CONF_OPTS = --disable-tiering --disable-ec-dynamic --disable-xmltest --disable-crypt-xlator --disable-georeplication --disable-ibverbs --disable-glupy --disable-gnfs --disable-cmocka --without-server GLUSTER_INSTALL_TARGET_OPTS = DESTDIR=$(TARGET_DIR) install From 1f6e72427f6ea14b3f0f4cdd2965f25bccd49b95 Mon Sep 17 00:00:00 2001 From: tstromberg Date: Wed, 16 Oct 2019 16:18:28 -0700 Subject: [PATCH 43/78] Remove trailing slash --- deploy/iso/minikube-iso/package/gluster/gluster.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/iso/minikube-iso/package/gluster/gluster.mk b/deploy/iso/minikube-iso/package/gluster/gluster.mk index c2d73f1853..35a761afd1 100644 --- a/deploy/iso/minikube-iso/package/gluster/gluster.mk +++ b/deploy/iso/minikube-iso/package/gluster/gluster.mk @@ -8,7 +8,7 @@ GLUSTER_VERSION = 4.1.5 # Official gluster site has SSL problems # https://bugzilla.redhat.com/show_bug.cgi?id=1572944 # GLUSTER_SITE = https://download.gluster.org/pub/gluster/glusterfs/4.1/$(GLUSTER_VERSION) -GLUSTER_SITE = http://download.openpkg.org/components/cache/glusterfs/ +GLUSTER_SITE = http://download.openpkg.org/components/cache/glusterfs GLUSTER_SOURCE = glusterfs-$(GLUSTER_VERSION).tar.gz GLUSTER_CONF_OPTS = --disable-tiering --disable-ec-dynamic --disable-xmltest --disable-crypt-xlator --disable-georeplication --disable-ibverbs --disable-glupy --disable-gnfs --disable-cmocka --without-server GLUSTER_INSTALL_TARGET_OPTS = DESTDIR=$(TARGET_DIR) install From 53136c8bb64e18d2a75e6fcd1b0e5bfbc3af23f0 Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Thu, 17 Oct 2019 11:23:55 -0700 Subject: [PATCH 44/78] Add load warning, fix profile deletion, make vbox iface cleanup less noisy --- hack/jenkins/common.sh | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/hack/jenkins/common.sh b/hack/jenkins/common.sh index 96a6658b37..034874d1ee 100755 --- a/hack/jenkins/common.sh +++ b/hack/jenkins/common.sh @@ -37,10 +37,20 @@ echo "job: ${JOB_NAME}" echo "test home: ${TEST_HOME}" echo "sudo: ${SUDO_PREFIX}" echo "kernel: $(uname -v)" +echo "uptime: $(uptime)" # Setting KUBECONFIG prevents the version ceck from erroring out due to permission issues echo "kubectl: $(env KUBECONFIG=${TEST_HOME} kubectl version --client --short=true)" echo "docker: $(docker version --format '{{ .Client.Version }}')" +readonly LOAD=$(uptime | egrep -o "load average.*: [0-9]" | cut -d" " -f3) +if [[ "${LOAD}" -gt 2 ]]; then + echo "" + echo "******************************* LOAD WARNING **************************" + echo "Load average is very high (${LOAD}), which may cause failures" + echo "******************************* LOAD WARNING **************************" + echo "" +fi + case "${VM_DRIVER}" in kvm2) echo "virsh: $(virsh --version)" @@ -100,17 +110,15 @@ echo "" echo ">> Cleaning up after previous test runs ..." for entry in $(ls ${TEST_ROOT}); do echo "* Cleaning stale test path: ${entry}" - for tunnel in $(find ${entry} -name tunnels.json -type f); do + for tunnel in $(find ${TEST_ROOT}/${entry} -name tunnels.json -type f); do env MINIKUBE_HOME="$(dirname ${tunnel})" ${MINIKUBE_BIN} tunnel --cleanup || true done - for home in $(find ${entry} -name .minikube -type d); do - env MINIKUBE_HOME="$(dirname ${home})" ${MINIKUBE_BIN} delete || true + for home in $(find ${TEST_ROOT}/${entry} -name .minikube -type d); do + env MINIKUBE_HOME="$(dirname ${home})" ${MINIKUBE_BIN} delete --all || true sudo rm -Rf "${home}" done - ${MINIKUBE_BIN} delete --all || true - for kconfig in $(find ${entry} -name kubeconfig -type f); do sudo rm -f "${kconfig}" done @@ -143,19 +151,21 @@ if type -P virsh; then fi if type -P vboxmanage; then - for guid in $(vboxmanage list vms | egrep -Eo '\{[-a-Z0-9]+\}'); do + for guid in $(vboxmanage list vms | grep -Eo '\{[-a-Z0-9]+\}'); do echo "- Removing stale VirtualBox VM: $guid" - vboxmanage startvm $guid --type emergencystop || true - vboxmanage unregistervm $guid || true + vboxmanage startvm "${guid}" --type emergencystop || true + vboxmanage unregistervm "${guid}" || true done - vboxmanage list hostonlyifs \ - | grep "^Name:" \ - | awk '{ print $2 }' \ - | xargs -n1 vboxmanage hostonlyif remove || true + ifaces=$(vboxmanage list hostonlyifs | grep -E "^Name:" | awk '{ printf $2 }') + for if in $ifaces; do + vboxmanage hostonlyif remove "${if}" || true + done echo ">> VirtualBox VM list after clean up (should be empty):" vboxmanage list vms || true + echo ">> VirtualBox interface list after clean up (should be empty):" + vboxmanage list hostonlyifs || true fi From 23e94a3257d0a9054e18e300211e2e1a710bdb20 Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Thu, 17 Oct 2019 11:37:14 -0700 Subject: [PATCH 45/78] Use full paths consistently in cleanup --- hack/jenkins/common.sh | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/hack/jenkins/common.sh b/hack/jenkins/common.sh index 034874d1ee..0061b3ba7f 100755 --- a/hack/jenkins/common.sh +++ b/hack/jenkins/common.sh @@ -109,27 +109,29 @@ mkdir -p "${TEST_ROOT}" echo "" echo ">> Cleaning up after previous test runs ..." for entry in $(ls ${TEST_ROOT}); do - echo "* Cleaning stale test path: ${entry}" - for tunnel in $(find ${TEST_ROOT}/${entry} -name tunnels.json -type f); do + test_path="${TEST_ROOT}/${entry}" + ls -lad "${test_path}" || continue + + echo "* Cleaning stale test path: ${test_path}" + for tunnel in $(find ${test_path} -name tunnels.json -type f); do env MINIKUBE_HOME="$(dirname ${tunnel})" ${MINIKUBE_BIN} tunnel --cleanup || true done - for home in $(find ${TEST_ROOT}/${entry} -name .minikube -type d); do + for home in $(find ${test_path} -name .minikube -type d); do env MINIKUBE_HOME="$(dirname ${home})" ${MINIKUBE_BIN} delete --all || true sudo rm -Rf "${home}" done - for kconfig in $(find ${entry} -name kubeconfig -type f); do + for kconfig in $(find ${test_path} -name kubeconfig -type f); do sudo rm -f "${kconfig}" done # Be very specific to avoid accidentally deleting other items, like wildcards or devices - if [[ -d "${entry}" ]]; then - rm -Rf "${entry}" || true - elif [[ -f "${entry}" ]]; then - rm -f "${entry}" || true + if [[ -d "${test_path}" ]]; then + rm -Rf "${test_path}" || true + elif [[ -f "${test_path}" ]]; then + rm -f "${test_path}" || true fi - done # sometimes tests left over zombie procs that won't exit From 554f553c9ee2fcaf64f3ae0d76ed35607555b55b Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Thu, 17 Oct 2019 11:54:52 -0700 Subject: [PATCH 46/78] Include top output with load warning --- hack/jenkins/common.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/hack/jenkins/common.sh b/hack/jenkins/common.sh index 0061b3ba7f..3ca3b6d84f 100755 --- a/hack/jenkins/common.sh +++ b/hack/jenkins/common.sh @@ -45,9 +45,15 @@ echo "docker: $(docker version --format '{{ .Client.Version }}')" readonly LOAD=$(uptime | egrep -o "load average.*: [0-9]" | cut -d" " -f3) if [[ "${LOAD}" -gt 2 ]]; then echo "" - echo "******************************* LOAD WARNING **************************" - echo "Load average is very high (${LOAD}), which may cause failures" - echo "******************************* LOAD WARNING **************************" + echo "********************** LOAD WARNING ********************************" + echo "Load average is very high (${LOAD}), which may cause failures. Top:" + if [[ "$(uname)" == "Darwin" ]]; then + # Two samples, macOS does not calculate CPU usage on the first one + top -l 2 -o cpu -n 5 | tail -n 15 + else + top -b -n1 | head -n 15 + fi + echo "********************** LOAD WARNING ********************************" echo "" fi From 10ff44e5826535bcb636fe31879226fa1cfd5109 Mon Sep 17 00:00:00 2001 From: Nanik T Date: Fri, 18 Oct 2019 06:28:24 +1100 Subject: [PATCH 47/78] Modify output text to make it more readable as per PR comment --- pkg/minikube/service/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/minikube/service/service.go b/pkg/minikube/service/service.go index fcc5bb7a7c..58a7264731 100644 --- a/pkg/minikube/service/service.go +++ b/pkg/minikube/service/service.go @@ -275,7 +275,7 @@ func WaitAndMaybeOpenService(api libmachine.API, namespace string, service strin chkSVC := func() error { return CheckService(namespace, service) } if err := retry.Expo(chkSVC, time.Duration(interval)*time.Second, time.Duration(wait)*time.Second); err != nil { - return errors.Wrapf(err, "Service %s was not found in %s namespace , please try with 'minikube service %s -n Y'", service, namespace, service) + return errors.Wrapf(err, "Service %s was not found in %q namespace. You may select another namespace by using 'minikube service %s -n ", service, namespace, service) } serviceURL, err := GetServiceURLsForService(api, namespace, service, urlTemplate) From a0a5b685f9d0b82d407d132b6c7997c24d1cfc84 Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Thu, 17 Oct 2019 12:38:02 -0700 Subject: [PATCH 48/78] Move delete --all test so that it is run in serial --- test/integration/a_download_only_test.go | 14 ++++++++++---- test/integration/start_stop_delete_test.go | 5 ----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/test/integration/a_download_only_test.go b/test/integration/a_download_only_test.go index 8e311b9d52..ff8869f23f 100644 --- a/test/integration/a_download_only_test.go +++ b/test/integration/a_download_only_test.go @@ -34,10 +34,8 @@ import ( "k8s.io/minikube/pkg/minikube/localpath" ) -// Note this test runs before all because filename is alphabetically first -// is used to cache images and binaries used by other parallel tests to avoid redownloading. -// TestDownloadOnly tests the --download-only option -func TestDownloadOnly(t *testing.T) { +// This test runs before others due to filename order. +func TestDownloadAndDeleteAll(t *testing.T) { profile := UniqueProfileName("download") ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) defer Cleanup(t, profile, cancel) @@ -79,5 +77,13 @@ func TestDownloadOnly(t *testing.T) { } }) } + t.Run("DeleteAll", func(t *testing.T) { + // This is a weird place to test profile deletion, but this test is serial, and we have an unneccesary profile to delete! + rr, err := Run(t, exec.CommandContext(ctx, Target(), "delete", "--all")) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } + }) }) + } diff --git a/test/integration/start_stop_delete_test.go b/test/integration/start_stop_delete_test.go index 1ed1f6b676..bf575baeee 100644 --- a/test/integration/start_stop_delete_test.go +++ b/test/integration/start_stop_delete_test.go @@ -139,11 +139,6 @@ func TestStartStop(t *testing.T) { if err != nil { t.Errorf("%s failed: %v", rr.Args, err) } - - rr, err = Run(t, exec.CommandContext(ctx, Target(), "delete", "--all")) - if err != nil { - t.Errorf("%s failed: %v", rr.Args, err) - } }) } }) From f75c26e31e63c1bb88c378cf9c6c108ba8290ede Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Thu, 17 Oct 2019 12:40:52 -0700 Subject: [PATCH 49/78] Rename serial tests file --- test/integration/Untitled-1 | 0 test/integration/{a_download_only_test.go => a_serial_tests.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/integration/Untitled-1 rename test/integration/{a_download_only_test.go => a_serial_tests.go} (100%) diff --git a/test/integration/Untitled-1 b/test/integration/Untitled-1 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/integration/a_download_only_test.go b/test/integration/a_serial_tests.go similarity index 100% rename from test/integration/a_download_only_test.go rename to test/integration/a_serial_tests.go From 21aeec60eacf85d827ca0afc3aaf5b50bb489c67 Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Thu, 17 Oct 2019 12:41:27 -0700 Subject: [PATCH 50/78] Remove obsolete comment --- test/integration/a_serial_tests.go | 1 - 1 file changed, 1 deletion(-) diff --git a/test/integration/a_serial_tests.go b/test/integration/a_serial_tests.go index ff8869f23f..6a45960241 100644 --- a/test/integration/a_serial_tests.go +++ b/test/integration/a_serial_tests.go @@ -16,7 +16,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -// a_download_only_test.go filename starts with a, for the purpose that it runs before all parallel tests and downloads the images and caches them. package integration import ( From e00868823947c0090aaaad860bf01100b5b6a373 Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Thu, 17 Oct 2019 12:55:56 -0700 Subject: [PATCH 51/78] Fix comments --- test/integration/a_serial_tests.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/integration/a_serial_tests.go b/test/integration/a_serial_tests.go index 6a45960241..78dd736525 100644 --- a/test/integration/a_serial_tests.go +++ b/test/integration/a_serial_tests.go @@ -33,7 +33,6 @@ import ( "k8s.io/minikube/pkg/minikube/localpath" ) -// This test runs before others due to filename order. func TestDownloadAndDeleteAll(t *testing.T) { profile := UniqueProfileName("download") ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) @@ -76,8 +75,8 @@ func TestDownloadAndDeleteAll(t *testing.T) { } }) } + // This is a weird place to test profile deletion, but this test is serial, and we have a profile to delete! t.Run("DeleteAll", func(t *testing.T) { - // This is a weird place to test profile deletion, but this test is serial, and we have an unneccesary profile to delete! rr, err := Run(t, exec.CommandContext(ctx, Target(), "delete", "--all")) if err != nil { t.Errorf("%s failed: %v", rr.Args, err) From b5f071d67fe23b9781789848623e5eafd4cb1a26 Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Thu, 17 Oct 2019 13:09:05 -0700 Subject: [PATCH 52/78] Fix 'grep: invalid character range' error on macOS --- hack/jenkins/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/jenkins/common.sh b/hack/jenkins/common.sh index 3ca3b6d84f..ccd9216160 100755 --- a/hack/jenkins/common.sh +++ b/hack/jenkins/common.sh @@ -159,7 +159,7 @@ if type -P virsh; then fi if type -P vboxmanage; then - for guid in $(vboxmanage list vms | grep -Eo '\{[-a-Z0-9]+\}'); do + for guid in $(vboxmanage list vms | grep -Eo '\{[a-zA-Z0-9-]+\}'); do echo "- Removing stale VirtualBox VM: $guid" vboxmanage startvm "${guid}" --type emergencystop || true vboxmanage unregistervm "${guid}" || true From e1f49c277bba71ac88fd0f567816fb881dcf92a2 Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Thu, 17 Oct 2019 13:53:36 -0700 Subject: [PATCH 53/78] Allow more time for gvisor to complete on slower machines --- test/integration/gvisor_addon_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/gvisor_addon_test.go b/test/integration/gvisor_addon_test.go index 7a4baec3c1..c5e2790bb6 100644 --- a/test/integration/gvisor_addon_test.go +++ b/test/integration/gvisor_addon_test.go @@ -33,7 +33,7 @@ func TestGvisorAddon(t *testing.T) { MaybeSlowParallel(t) profile := UniqueProfileName("gvisor") - ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) defer func() { CleanupWithLogs(t, profile, cancel) }() From 789cc7a55a28224e78d7278a77b43b432181bf28 Mon Sep 17 00:00:00 2001 From: Nanik T Date: Fri, 18 Oct 2019 08:07:09 +1100 Subject: [PATCH 54/78] Restructure code based on PR comments. * When nil is returned from function just return back * Restructure the output so that it will make more sense for the user --- cmd/minikube/cmd/start.go | 78 ++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 42 deletions(-) diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index d025635c00..ab5840363a 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -19,6 +19,7 @@ package cmd import ( "encoding/json" "fmt" + "math" "net" "net/url" "os" @@ -132,11 +133,11 @@ var ( ) type kubectlversion struct { - CVersion ClientVersion `json:"clientVersion"` - SVersion ClientVersion `json:"serverVersion"` + CVersion VersionInfo `json:"clientVersion"` + SVersion VersionInfo `json:"serverVersion"` } -type ClientVersion struct { +type VersionInfo struct { Major string `json:"major"` Minor string `json:"minor"` GitVersion string `json:"gitVersion"` @@ -491,55 +492,48 @@ func showVersionInfo(k8sVersion string, cr cruntime.Manager) { /** Function to check for kubectl. The checking is to compare -the version reported by both the client and server. It is -that kubectl will be of the same version or 1 lower than -the kubernetes version. +the version reported by both the client and server. Checking +is based on what is outlined in Kubernetes document +https://kubernetes.io/docs/setup/release/version-skew-policy/#kubectl */ func showKubectlConnectInfo(kcs *kubeconfig.Settings) { var output []byte clientVersion := kubectlversion{} - serverVersion := kubectlversion{} - - path, err := exec.LookPath("kubectl") - - if err != nil { - out.T(out.Tip, "For best results, install kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/") - } else { - glog.Infof("Kubectl found at the following location %s. Let's execute and get the result", path) - output, err = exec.Command(path, "version", "--output=json").Output() - - // ...once we get something back do some version checking - if err == nil { - glog.Infof("Received output from kubectl %s", output) - - // unmarshal both the {client} - clientjsonErr := json.Unmarshal(output, &clientVersion) - - // ....... and {server} json - serverjsonErr := json.Unmarshal(output, &serverVersion) - - if (clientjsonErr != nil) || (serverjsonErr != nil) { - glog.Infof("There was an error processing the json output") - } else { - // obtain the minor version for both - serverMinor, _ := strconv.Atoi(serverVersion.SVersion.Minor) - clientMinor, _ := strconv.Atoi(serverVersion.CVersion.Minor) - - if clientMinor < serverMinor { - out.T(out.Tip, "The version of kubectl {{.kubectl}} installed is incompatible with your Kubernetes {{.kubernetes}} deployment. Please upgrade/downgrade as necessary, or use minikube kubectlto connect to your cluster", - out.V{"kubectl": clientVersion.CVersion.GitVersion, "kubernetes": serverVersion.SVersion.GitVersion}) - } - } - } else { - out.T(out.Tip, "For best results, install kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/") - } - } if kcs.KeepContext { out.T(out.Kubectl, "To connect to this cluster, use: kubectl --context={{.name}}", out.V{"name": kcs.ClusterName}) } else { out.T(out.Ready, `Done! kubectl is now configured to use "{{.name}}"`, out.V{"name": cfg.GetMachineName()}) } + + path, err := exec.LookPath("kubectl") + // ...not found just print and return + if err != nil { + out.T(out.Tip, "For best results, install kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/") + return + } + + output, err = exec.Command(path, "version", "--output=json").Output() + if err != nil { + return + } + glog.Infof("Received output from kubectl %s", output) + + // unmarshal the json + output = []byte("Nanik") + clientjsonErr := json.Unmarshal(output, &clientVersion) + if clientjsonErr != nil { + glog.Infof("There was an error processing kubectl json output.") + return + } + // obtain the minor version for both client & server + serverMinor, _ := strconv.Atoi(clientVersion.SVersion.Minor) + clientMinor, _ := strconv.Atoi(clientVersion.CVersion.Minor) + + if math.Abs(float64(clientMinor-serverMinor)) > 1 { + out.T(out.Tip, "{{.path}} is version {{.clientMinor}}, and is incompatible with your specified Kubernetes version. You will need to update {{.path}} or use 'minikube kubectl' to connect with this cluster", + out.V{"path": path, "clientMinor": clientMinor}) + } } func selectDriver(oldConfig *cfg.Config) string { From 4b2f962f0cb9dfdebeba50ec67116ce5206275c4 Mon Sep 17 00:00:00 2001 From: Josh Woodcock Date: Mon, 7 Oct 2019 08:20:08 -0500 Subject: [PATCH 55/78] Add json output for profile list --- cmd/minikube/cmd/config/profile_list.go | 117 +++++++++++++++++------- 1 file changed, 86 insertions(+), 31 deletions(-) diff --git a/cmd/minikube/cmd/config/profile_list.go b/cmd/minikube/cmd/config/profile_list.go index b6aa8b91e7..854a3ab07f 100644 --- a/cmd/minikube/cmd/config/profile_list.go +++ b/cmd/minikube/cmd/config/profile_list.go @@ -17,9 +17,11 @@ limitations under the License. package config import ( + "encoding/json" "fmt" "os" "strconv" + "strings" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/exit" @@ -29,48 +31,101 @@ import ( "github.com/spf13/cobra" ) +var ( + output string +) + var profileListCmd = &cobra.Command{ Use: "list", Short: "Lists all minikube profiles.", Long: "Lists all valid minikube profiles and detects all possible invalid profiles.", Run: func(cmd *cobra.Command, args []string) { - var validData [][]string - - table := tablewriter.NewWriter(os.Stdout) - table.SetHeader([]string{"Profile", "VM Driver", "NodeIP", "Node Port", "Kubernetes Version"}) - table.SetAutoFormatHeaders(false) - table.SetBorders(tablewriter.Border{Left: true, Top: true, Right: true, Bottom: true}) - table.SetCenterSeparator("|") - validProfiles, invalidProfiles, err := config.ListProfiles() - - if len(validProfiles) == 0 || err != nil { - exit.UsageT("No minikube profile was found. You can create one using `minikube start`.") - } - for _, p := range validProfiles { - validData = append(validData, []string{p.Name, p.Config.MachineConfig.VMDriver, p.Config.KubernetesConfig.NodeIP, strconv.Itoa(p.Config.KubernetesConfig.NodePort), p.Config.KubernetesConfig.KubernetesVersion}) + switch strings.ToLower(output) { + case "json": + PrintProfilesJSON() + case "table": + PrintProfilesTable() + default: + exit.WithCodeT(exit.BadUsage, fmt.Sprintf("invalid output format: %s. Valid values: 'table', 'json'", output)) } - table.AppendBulk(validData) - table.Render() - - if invalidProfiles != nil { - out.T(out.WarningType, "Found {{.number}} invalid profile(s) ! ", out.V{"number": len(invalidProfiles)}) - for _, p := range invalidProfiles { - out.T(out.Empty, "\t "+p.Name) - } - out.T(out.Tip, "You can delete them using the following command(s): ") - for _, p := range invalidProfiles { - out.String(fmt.Sprintf("\t $ minikube delete -p %s \n", p.Name)) - } - - } - if err != nil { - exit.WithCodeT(exit.Config, fmt.Sprintf("error loading profiles: %v", err)) - } }, } +func PrintProfilesTable() { + + var validData [][]string + + table := tablewriter.NewWriter(os.Stdout) + table.SetHeader([]string{"Profile", "VM Driver", "NodeIP", "Node Port", "Kubernetes Version"}) + table.SetAutoFormatHeaders(false) + table.SetBorders(tablewriter.Border{Left: true, Top: true, Right: true, Bottom: true}) + table.SetCenterSeparator("|") + validProfiles, invalidProfiles, err := config.ListProfiles() + + if len(validProfiles) == 0 || err != nil { + exit.UsageT("No minikube profile was found. You can create one using `minikube start`.") + } + for _, p := range validProfiles { + validData = append(validData, []string{p.Name, p.Config.MachineConfig.VMDriver, p.Config.KubernetesConfig.NodeIP, strconv.Itoa(p.Config.KubernetesConfig.NodePort), p.Config.KubernetesConfig.KubernetesVersion}) + } + + table.AppendBulk(validData) + table.Render() + + if invalidProfiles != nil { + out.T(out.WarningType, "Found {{.number}} invalid profile(s) ! ", out.V{"number": len(invalidProfiles)}) + for _, p := range invalidProfiles { + out.T(out.Empty, "\t "+p.Name) + } + out.T(out.Tip, "You can delete them using the following command(s): ") + for _, p := range invalidProfiles { + out.String(fmt.Sprintf("\t $ minikube delete -p %s \n", p.Name)) + } + + } + + if err != nil { + exit.WithCodeT(exit.Config, fmt.Sprintf("error loading profiles: %v", err)) + } + +} + +func PrintProfilesJSON() { + validProfiles, invalidProfiles, err := config.ListProfiles() + + var valid []*config.Profile + var invalid []*config.Profile + + if validProfiles != nil { + valid = validProfiles + } else { + valid = []*config.Profile{} + } + + if invalidProfiles != nil { + invalid = invalidProfiles + } else { + invalid = []*config.Profile{} + } + + var body = map[string]interface{}{} + + if err == nil { + body["valid"] = valid + body["invalid"] = invalid + jsonString, _ := json.Marshal(body) + out.String(string(jsonString)) + } else { + body["error"] = err + jsonString, _ := json.Marshal(body) + out.String(string(jsonString)) + os.Exit(exit.Failure) + } +} + func init() { + profileListCmd.Flags().StringVarP(&output, "output", "o", "table", "The output format. One of 'json', 'table'") ProfileCmd.AddCommand(profileListCmd) } From 4a4fa6567ad1e676cbc17172a9cae650e508d0f7 Mon Sep 17 00:00:00 2001 From: Josh Woodcock Date: Fri, 11 Oct 2019 12:16:26 -0500 Subject: [PATCH 56/78] Add tests for profile list command --- test/integration/functional_test.go | 38 ++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/test/integration/functional_test.go b/test/integration/functional_test.go index 69a8864e93..3c001e48e8 100644 --- a/test/integration/functional_test.go +++ b/test/integration/functional_test.go @@ -295,12 +295,48 @@ func validateLogsCmd(ctx context.Context, t *testing.T, profile string) { } } -// validateProfileCmd asserts basic "profile" command functionality +// validateProfileCmd asserts "profile" command functionality func validateProfileCmd(ctx context.Context, t *testing.T, profile string) { rr, err := Run(t, exec.CommandContext(ctx, Target(), "profile", "list")) if err != nil { t.Errorf("%s failed: %v", rr.Args, err) } + + // Table output + listLines := strings.Split(strings.TrimSpace(rr.Stdout.String()), "\n") + profileExists := false + for i := 3; i < (len(listLines) - 1); i++ { + profileLine := listLines[i] + if strings.Contains(profileLine, profile) { + profileExists = true + break + } + } + if !profileExists { + t.Errorf("%s failed: Missing profile '%s'. Got '\n%s\n'", rr.Args, profile, rr.Stdout.String()) + } + + // Json output + rr, err = Run(t, exec.CommandContext(ctx, Target(), "profile", "list", "--output", "json")) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } + var jsonObject map[string][]map[string]interface{} + err = json.Unmarshal(rr.Stdout.Bytes(), &jsonObject) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } + validProfiles := jsonObject["valid"] + profileExists = false + for _, profileObject := range validProfiles { + if profileObject["Name"] == profile { + profileExists = true + break + } + } + if !profileExists { + t.Errorf("%s failed: Missing profile '%s'. Got '\n%s\n'", rr.Args, profile, rr.Stdout.String()) + } } // validateServiceCmd asserts basic "service" command functionality From d758672c8b64b8001f40c44af2f9d60e355d51fc Mon Sep 17 00:00:00 2001 From: Josh Woodcock Date: Fri, 11 Oct 2019 14:11:43 -0500 Subject: [PATCH 57/78] Remove function exports for profile list output types --- cmd/minikube/cmd/config/profile_list.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/minikube/cmd/config/profile_list.go b/cmd/minikube/cmd/config/profile_list.go index 854a3ab07f..b79bf162cc 100644 --- a/cmd/minikube/cmd/config/profile_list.go +++ b/cmd/minikube/cmd/config/profile_list.go @@ -43,9 +43,9 @@ var profileListCmd = &cobra.Command{ switch strings.ToLower(output) { case "json": - PrintProfilesJSON() + printProfilesJSON() case "table": - PrintProfilesTable() + printProfilesTable() default: exit.WithCodeT(exit.BadUsage, fmt.Sprintf("invalid output format: %s. Valid values: 'table', 'json'", output)) } @@ -53,7 +53,7 @@ var profileListCmd = &cobra.Command{ }, } -func PrintProfilesTable() { +var printProfilesTable = func() { var validData [][]string @@ -92,7 +92,7 @@ func PrintProfilesTable() { } -func PrintProfilesJSON() { +var printProfilesJSON = func() { validProfiles, invalidProfiles, err := config.ListProfiles() var valid []*config.Profile From 824c911c428277976eba57d4110b17854df80833 Mon Sep 17 00:00:00 2001 From: Nanik T Date: Tue, 15 Oct 2019 18:34:05 +1100 Subject: [PATCH 58/78] Add validation checking for minikube profile Fixes : #4883 New function ProfileNameInReservedKeywords(..) has been added inside pkg/minikube/config/profile.go The new function perform validation to make sure the profile name is not in the list of keywords. Following are the keywords that are used: start, stop, status, delete, config, open, profile, addons, cache, logs The checking is case insensitive to cover combo of upper and lower case --- cmd/minikube/cmd/config/profile.go | 9 +++++++++ pkg/minikube/config/profile.go | 14 +++++++++++++- pkg/minikube/config/profile_test.go | 26 ++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/cmd/minikube/cmd/config/profile.go b/cmd/minikube/cmd/config/profile.go index cbf6f1fe6d..64f0f372f5 100644 --- a/cmd/minikube/cmd/config/profile.go +++ b/cmd/minikube/cmd/config/profile.go @@ -45,6 +45,15 @@ var ProfileCmd = &cobra.Command{ } profile := args[0] + /** + we need to add code over here to check whether the profile + name is in the list of reserved keywords + */ + if pkgConfig.ProfileNameInReservedKeywords(profile) { + out.ErrT(out.FailureType, `Profile name "{{.profilename}}" is minikube keyword. To delete profile use command minikube delete -p `, out.V{"profilename": profile}) + os.Exit(0) + } + if profile == "default" { profile = "minikube" } else { diff --git a/pkg/minikube/config/profile.go b/pkg/minikube/config/profile.go index 2c09f4b446..b75ade5680 100644 --- a/pkg/minikube/config/profile.go +++ b/pkg/minikube/config/profile.go @@ -21,18 +21,20 @@ import ( "io/ioutil" "os" "path/filepath" + "strings" "github.com/golang/glog" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/util/lock" ) +var keywords = []string{"start", "stop", "status", "delete", "config", "open", "profile", "addons", "cache", "logs"} + // IsValid checks if the profile has the essential info needed for a profile func (p *Profile) IsValid() bool { if p.Config == nil { return false } - if p.Config.MachineConfig.VMDriver == "" { return false } @@ -42,6 +44,16 @@ func (p *Profile) IsValid() bool { return true } +// check if the profile is an internal keywords +func ProfileNameInReservedKeywords(name string) bool { + for _, v := range keywords { + if strings.EqualFold(v, name) { + return true + } + } + return false +} + // ProfileExists returns true if there is a profile config (regardless of being valid) func ProfileExists(name string, miniHome ...string) bool { miniPath := localpath.MiniPath() diff --git a/pkg/minikube/config/profile_test.go b/pkg/minikube/config/profile_test.go index 2cd674a8ef..8852ea9b6f 100644 --- a/pkg/minikube/config/profile_test.go +++ b/pkg/minikube/config/profile_test.go @@ -72,6 +72,32 @@ func TestListProfiles(t *testing.T) { } } +func TestProfileNameInReservedKeywords(t *testing.T) { + var testCases = []struct { + name string + expected bool + }{ + {"start", true}, + {"stop", true}, + {"status", true}, + {"delete", true}, + {"config", true}, + {"open", true}, + {"profile", true}, + {"addons", true}, + {"cache", true}, + {"logs", true}, + {"myprofile", false}, + {"log", false}, + } + for _, tt := range testCases { + got := ProfileNameInReservedKeywords(tt.name) + if got != tt.expected { + t.Errorf("expected ProfileNameInReservedKeywords(%s)=%t but got %t ", tt.name, tt.expected, got) + } + } +} + func TestProfileExists(t *testing.T) { miniDir, err := filepath.Abs("./testdata/.minikube2") if err != nil { From b132b048092a5cd74511daf0ce413b9bfbac89a4 Mon Sep 17 00:00:00 2001 From: Josh Woodcock Date: Fri, 11 Oct 2019 13:34:50 -0500 Subject: [PATCH 59/78] Add json output for addons list --- cmd/minikube/cmd/config/addons_list.go | 61 +++++++++++++++++++++++--- test/integration/functional_test.go | 11 +++++ 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/cmd/minikube/cmd/config/addons_list.go b/cmd/minikube/cmd/config/addons_list.go index 3a3b50ac05..08492a3678 100644 --- a/cmd/minikube/cmd/config/addons_list.go +++ b/cmd/minikube/cmd/config/addons_list.go @@ -17,18 +17,23 @@ limitations under the License. package config import ( + "encoding/json" + "fmt" "os" "sort" + "strings" "text/template" "github.com/spf13/cobra" "k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/exit" + "k8s.io/minikube/pkg/minikube/out" ) const defaultAddonListFormat = "- {{.AddonName}}: {{.AddonStatus}}\n" var addonListFormat string +var addonListOutput string // AddonListTemplate represents the addon list template type AddonListTemplate struct { @@ -44,9 +49,18 @@ var addonsListCmd = &cobra.Command{ if len(args) != 0 { exit.UsageT("usage: minikube addons list") } - err := addonList() - if err != nil { - exit.WithError("addon list failed", err) + + if addonListOutput != "list" && addonListFormat != defaultAddonListFormat { + exit.UsageT("Cannot use both --output and --format options") + } + + switch strings.ToLower(addonListOutput) { + case "list": + printAddonsList() + case "json": + printAddonsJSON() + default: + exit.WithCodeT(exit.BadUsage, fmt.Sprintf("invalid output format: %s. Valid values: 'list', 'json'", addonListOutput)) } }, } @@ -59,17 +73,25 @@ func init() { defaultAddonListFormat, `Go template format string for the addon list output. The format for Go templates can be found here: https://golang.org/pkg/text/template/ For the list of accessible variables for the template, see the struct values here: https://godoc.org/k8s.io/minikube/cmd/minikube/cmd/config#AddonListTemplate`) + + addonsListCmd.Flags().StringVarP( + &addonListOutput, + "output", + "o", + "list", + `minikube addons list --output OUTPUT. json, list`) + AddonsCmd.AddCommand(addonsListCmd) } -func stringFromStatus(addonStatus bool) string { +var stringFromStatus = func(addonStatus bool) string { if addonStatus { return "enabled" } return "disabled" } -func addonList() error { +var printAddonsList = func() { addonNames := make([]string, 0, len(assets.Addons)) for addonName := range assets.Addons { addonNames = append(addonNames, addonName) @@ -80,7 +102,7 @@ func addonList() error { addonBundle := assets.Addons[addonName] addonStatus, err := addonBundle.IsEnabled() if err != nil { - return err + exit.WithError("Error getting addons status", err) } tmpl, err := template.New("list").Parse(addonListFormat) if err != nil { @@ -92,5 +114,30 @@ func addonList() error { exit.WithError("Error executing list template", err) } } - return nil +} + +var printAddonsJSON = func() { + addonNames := make([]string, 0, len(assets.Addons)) + for addonName := range assets.Addons { + addonNames = append(addonNames, addonName) + } + sort.Strings(addonNames) + + addonsMap := map[string]map[string]interface{}{} + + for _, addonName := range addonNames { + addonBundle := assets.Addons[addonName] + + addonStatus, err := addonBundle.IsEnabled() + if err != nil { + exit.WithError("Error getting addons status", err) + } + + addonsMap[addonName] = map[string]interface{}{ + "Status": stringFromStatus(addonStatus), + } + } + jsonString, _ := json.Marshal(addonsMap) + + out.String(string(jsonString)) } diff --git a/test/integration/functional_test.go b/test/integration/functional_test.go index 7db6a99411..f6ecb99c7c 100644 --- a/test/integration/functional_test.go +++ b/test/integration/functional_test.go @@ -360,6 +360,17 @@ func validateAddonsCmd(ctx context.Context, t *testing.T, profile string) { t.Errorf("Plugin output did not match expected custom format. Got: %s", line) } } + + // Json output + rr, err = Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "addons", "list", "-o", "json")) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } + var jsonObject map[string]interface{} + err = json.Unmarshal(rr.Stdout.Bytes(), &jsonObject) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } } // validateSSHCmd asserts basic "ssh" command functionality From 3cf2830705304ab6ea3afa07539e769a7b9baedd Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Thu, 17 Oct 2019 14:48:41 -0700 Subject: [PATCH 60/78] Add test to ensure addon state is mutable for stopped clusters --- test/integration/addons_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/integration/addons_test.go b/test/integration/addons_test.go index 2b22e8cad2..e184b8e220 100644 --- a/test/integration/addons_test.go +++ b/test/integration/addons_test.go @@ -65,6 +65,20 @@ func TestAddons(t *testing.T) { }) } }) + + // Assert that disable/enable works offline + rr, err = Run(t, exec.CommandContext(ctx, Target(), "stop", "-p", profile)) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } + rr, err = Run(t, exec.CommandContext(ctx, Target(), "addons", "enable", "dashboard", "-p", profile)) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } + rr, err = Run(t, exec.CommandContext(ctx, Target(), "addons", "disable", "dashboard", "-p", profile)) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } } func validateIngressAddon(ctx context.Context, t *testing.T, profile string) { From 2180c1405b8de6e0205956e6f9b68bc0d4522521 Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Thu, 17 Oct 2019 16:23:21 -0700 Subject: [PATCH 61/78] Ensure that delete succeeds even if cluster is unavailable --- cmd/minikube/cmd/delete.go | 2 +- pkg/minikube/cluster/cluster.go | 8 +++++--- test/integration/a_serial_tests.go | 7 +++++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/cmd/minikube/cmd/delete.go b/cmd/minikube/cmd/delete.go index 6aac39c98f..a0b14ec63f 100644 --- a/cmd/minikube/cmd/delete.go +++ b/cmd/minikube/cmd/delete.go @@ -177,7 +177,7 @@ func deleteProfile(profile *pkg_config.Profile) error { if err = cluster.DeleteHost(api); err != nil { switch errors.Cause(err).(type) { case mcnerror.ErrHostDoesNotExist: - out.T(out.Meh, `"{{.name}}" cluster does not exist. Proceeding ahead with cleanup.`, out.V{"name": profile}) + out.T(out.Meh, `"{{.name}}" cluster does not exist. Proceeding ahead with cleanup.`, out.V{"name": profile.Name}) default: out.T(out.FailureType, "Failed to delete cluster: {{.error}}", out.V{"error": err}) out.T(out.Notice, `You may need to manually remove the "{{.name}}" VM from your hypervisor`, out.V{"name": profile.Name}) diff --git a/pkg/minikube/cluster/cluster.go b/pkg/minikube/cluster/cluster.go index 84e43632fa..7526daf324 100644 --- a/pkg/minikube/cluster/cluster.go +++ b/pkg/minikube/cluster/cluster.go @@ -270,16 +270,18 @@ func StopHost(api libmachine.API) error { // DeleteHost deletes the host VM. func DeleteHost(api libmachine.API) error { - host, err := api.Load(cfg.GetMachineName()) + name := cfg.GetMachineName() + host, err := api.Load(name) if err != nil { return errors.Wrap(err, "load") } - // Get the status of the host. Ensure that it exists before proceeding ahead. status, err := GetHostStatus(api) if err != nil { - exit.WithCodeT(exit.Failure, "Unable to get the status of the cluster.") + // Warn, but proceed + out.WarningT("Unable to get the status of the {{.name}} cluster.", out.V{"name": name}) } + if status == state.None.String() { return mcnerror.ErrHostDoesNotExist{Name: host.Name} } diff --git a/test/integration/a_serial_tests.go b/test/integration/a_serial_tests.go index 78dd736525..7e4b604eff 100644 --- a/test/integration/a_serial_tests.go +++ b/test/integration/a_serial_tests.go @@ -82,6 +82,13 @@ func TestDownloadAndDeleteAll(t *testing.T) { t.Errorf("%s failed: %v", rr.Args, err) } }) + // Delete should always succeed, even if previously partially or fully deleted. + t.Run("DeleteAlwaysSucceeds", func(t *testing.T) { + rr, err := Run(t, exec.CommandContext(ctx, Target(), "delete", "-p", profile)) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } + }) }) } From b9bd1ba8d6e8b326a9e689667eaccbd0cead2acb Mon Sep 17 00:00:00 2001 From: tstromberg Date: Fri, 18 Oct 2019 15:17:51 -0700 Subject: [PATCH 62/78] Rewrite delete_test to run without side effects --- cmd/minikube/cmd/delete_test.go | 547 ++++++++------------------------ go.mod | 3 +- go.sum | 8 +- 3 files changed, 141 insertions(+), 417 deletions(-) diff --git a/cmd/minikube/cmd/delete_test.go b/cmd/minikube/cmd/delete_test.go index 042b86dd4c..69a37be735 100644 --- a/cmd/minikube/cmd/delete_test.go +++ b/cmd/minikube/cmd/delete_test.go @@ -22,450 +22,171 @@ import ( "path/filepath" "testing" + "github.com/google/go-cmp/cmp" + "github.com/otiai10/copy" "github.com/spf13/viper" + "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/localpath" ) -func TestDeleteProfileWithValidConfig(t *testing.T) { - testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube" - miniDir, err := filepath.Abs(testMinikubeDir) - - if err != nil { - t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err) +// except returns a list of strings, minus the excluded ones +func exclude(vals []string, exclude []string) []string { + result := []string{} + for _, v := range vals { + excluded := false + for _, e := range exclude { + if e == v { + excluded = true + continue + } + } + if !excluded { + result = append(result, v) + } } - - err = os.Setenv(localpath.MinikubeHome, miniDir) - if err != nil { - t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome) - } - - files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")) - numberOfProfileDirs := len(files) - - files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")) - numberOfMachineDirs := len(files) - - profileToDelete := "p1" - profile, _ := config.LoadProfile(profileToDelete) - - errs := DeleteProfiles([]*config.Profile{profile}) - - if len(errs) > 0 { - HandleDeletionErrors(errs) - t.Fatal("Errors while deleting profiles") - } - - pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) - } - - pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) { - t.Fatal("Did not delete exactly one profile") - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != (numberOfMachineDirs - 1) { - t.Fatal("Did not delete exactly one profile") - } - - viper.Set(config.MachineProfile, "") + return result } -func TestDeleteProfileWithEmptyProfileConfig(t *testing.T) { - testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube" - miniDir, err := filepath.Abs(testMinikubeDir) - +func fileNames(path string) ([]string, error) { + result := []string{} + fis, err := ioutil.ReadDir(path) if err != nil { - t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err) + return result, err } - - err = os.Setenv(localpath.MinikubeHome, miniDir) - if err != nil { - t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome) + for _, fi := range fis { + result = append(result, fi.Name()) } - - files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")) - numberOfProfileDirs := len(files) - - files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")) - numberOfMachineDirs := len(files) - - profileToDelete := "p2_empty_profile_config" - profile, _ := config.LoadProfile(profileToDelete) - - errs := DeleteProfiles([]*config.Profile{profile}) - - if len(errs) > 0 { - HandleDeletionErrors(errs) - t.Fatal("Errors while deleting profiles") - } - - pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) - } - - pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) { - t.Fatal("Did not delete exactly one profile") - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != (numberOfMachineDirs - 1) { - t.Fatal("Did not delete exactly one profile") - } - - viper.Set(config.MachineProfile, "") + return result, nil } -func TestDeleteProfileWithInvalidProfileConfig(t *testing.T) { - testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube" - miniDir, err := filepath.Abs(testMinikubeDir) - +func TestDeleteProfile(t *testing.T) { + td, err := ioutil.TempDir("", "single") if err != nil { - t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err) + t.Fatalf("tempdir: %v", err) } - - err = os.Setenv(localpath.MinikubeHome, miniDir) + err = copy.Copy("../../../pkg/minikube/config/testdata/delete-single", td) if err != nil { - t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome) + t.Fatalf("copy: %v", err) } - files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")) - numberOfProfileDirs := len(files) - - files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")) - numberOfMachineDirs := len(files) - - profileToDelete := "p3_invalid_profile_config" - profile, _ := config.LoadProfile(profileToDelete) - - errs := DeleteProfiles([]*config.Profile{profile}) - - if len(errs) > 0 { - HandleDeletionErrors(errs) - t.Fatal("Errors while deleting profiles") + tests := []struct { + name string + profile string + expected []string + }{ + {"normal", "p1", []string{"p1"}}, + {"empty-profile", "p2_empty_profile_config", []string{"p2_empty_profile_config"}}, + {"invalid-profile", "p3_invalid_profile_config", []string{"p3_invalid_profile_config"}}, + {"partial-profile", "p4_partial_profile_config", []string{"p4_partial_profile_config"}}, + {"missing-mach", "p5_missing_machine_config", []string{"p5_missing_machine_config"}}, + {"empty-mach", "p6_empty_machine_config", []string{"p6_empty_machine_config"}}, + {"invalid-mach", "p7_invalid_machine_config", []string{"p7_invalid_machine_config"}}, + {"partial-mach", "p8_partial_machine_config", []string{"p8_partial_machine_config"}}, } - pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err = os.Setenv(localpath.MinikubeHome, td) + if err != nil { + t.Errorf("setenv: %v", err) + } + + beforeProfiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles")) + if err != nil { + t.Errorf("readdir: %v", err) + } + beforeMachines, err := fileNames(filepath.Join(localpath.MiniPath(), "machines")) + if err != nil { + t.Errorf("readdir: %v", err) + } + + profile, err := config.LoadProfile(tt.profile) + if err != nil { + t.Logf("load failure: %v", err) + } + + errs := DeleteProfiles([]*config.Profile{profile}) + if len(errs) > 0 { + HandleDeletionErrors(errs) + t.Errorf("Errors while deleting profiles: %v", errs) + } + pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath()) + if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) { + t.Errorf("Profile folder of profile \"%s\" was not deleted", profile.Name) + } + + pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath()) + if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) { + t.Errorf("Profile folder of profile \"%s\" was not deleted", profile.Name) + } + + afterProfiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles")) + if err != nil { + t.Errorf("readdir profiles: %v", err) + } + + afterMachines, err := fileNames(filepath.Join(localpath.MiniPath(), "machines")) + if err != nil { + t.Errorf("readdir machines: %v", err) + } + + expectedProfiles := exclude(beforeProfiles, tt.expected) + if diff := cmp.Diff(expectedProfiles, afterProfiles); diff != "" { + t.Errorf("profiles mismatch (-want +got):\n%s", diff) + } + + expectedMachines := exclude(beforeMachines, tt.expected) + if diff := cmp.Diff(expectedMachines, afterMachines); diff != "" { + t.Errorf("machines mismatch (-want +got):\n%s", diff) + } + + viper.Set(config.MachineProfile, "") + }) } - - pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) { - t.Fatal("Did not delete exactly one profile") - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != (numberOfMachineDirs - 1) { - t.Fatal("Did not delete exactly one profile") - } - - viper.Set(config.MachineProfile, "") -} - -func TestDeleteProfileWithPartialProfileConfig(t *testing.T) { - testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube" - miniDir, err := filepath.Abs(testMinikubeDir) - - if err != nil { - t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err) - } - - err = os.Setenv(localpath.MinikubeHome, miniDir) - if err != nil { - t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome) - } - - files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")) - numberOfProfileDirs := len(files) - - files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")) - numberOfMachineDirs := len(files) - - profileToDelete := "p4_partial_profile_config" - profile, _ := config.LoadProfile(profileToDelete) - - errs := DeleteProfiles([]*config.Profile{profile}) - - if len(errs) > 0 { - HandleDeletionErrors(errs) - t.Fatal("Errors while deleting profiles") - } - - pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) - } - - pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) { - t.Fatal("Did not delete exactly one profile") - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != (numberOfMachineDirs - 1) { - t.Fatal("Did not delete exactly one profile") - } - - viper.Set(config.MachineProfile, "") -} - -func TestDeleteProfileWithMissingMachineConfig(t *testing.T) { - testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube" - miniDir, err := filepath.Abs(testMinikubeDir) - - if err != nil { - t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err) - } - - err = os.Setenv(localpath.MinikubeHome, miniDir) - if err != nil { - t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome) - } - - files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")) - numberOfProfileDirs := len(files) - - files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")) - numberOfMachineDirs := len(files) - - profileToDelete := "p5_missing_machine_config" - profile, _ := config.LoadProfile(profileToDelete) - - errs := DeleteProfiles([]*config.Profile{profile}) - - if len(errs) > 0 { - HandleDeletionErrors(errs) - t.Fatal("Errors while deleting profiles") - } - - pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) - } - - pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) { - t.Fatal("Did not delete exactly one profile") - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != numberOfMachineDirs { - t.Fatal("Deleted a machine config when it should not") - } - - viper.Set(config.MachineProfile, "") -} - -func TestDeleteProfileWithEmptyMachineConfig(t *testing.T) { - testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube" - miniDir, err := filepath.Abs(testMinikubeDir) - - if err != nil { - t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err) - } - - err = os.Setenv(localpath.MinikubeHome, miniDir) - if err != nil { - t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome) - } - - files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")) - numberOfProfileDirs := len(files) - - files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")) - numberOfMachineDirs := len(files) - - profileToDelete := "p6_empty_machine_config" - profile, _ := config.LoadProfile(profileToDelete) - - errs := DeleteProfiles([]*config.Profile{profile}) - - if len(errs) > 0 { - HandleDeletionErrors(errs) - t.Fatal("Errors while deleting profiles") - } - - pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) - } - - pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) { - t.Fatal("Did not delete exactly one profile") - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != (numberOfMachineDirs - 1) { - t.Fatal("Did not delete exactly one profile") - } - - viper.Set(config.MachineProfile, "") -} - -func TestDeleteProfileWithInvalidMachineConfig(t *testing.T) { - testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube" - miniDir, err := filepath.Abs(testMinikubeDir) - - if err != nil { - t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err) - } - - err = os.Setenv(localpath.MinikubeHome, miniDir) - if err != nil { - t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome) - } - - files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")) - numberOfProfileDirs := len(files) - - files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")) - numberOfMachineDirs := len(files) - - profileToDelete := "p7_invalid_machine_config" - profile, _ := config.LoadProfile(profileToDelete) - - errs := DeleteProfiles([]*config.Profile{profile}) - - if len(errs) > 0 { - HandleDeletionErrors(errs) - t.Fatal("Errors while deleting profiles") - } - - pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) - } - - pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) { - t.Fatal("Did not delete exactly one profile") - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != (numberOfMachineDirs - 1) { - t.Fatal("Did not delete exactly one profile") - } - - viper.Set(config.MachineProfile, "") -} - -func TestDeleteProfileWithPartialMachineConfig(t *testing.T) { - testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube" - miniDir, err := filepath.Abs(testMinikubeDir) - - if err != nil { - t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err) - } - - err = os.Setenv(localpath.MinikubeHome, miniDir) - if err != nil { - t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome) - } - - files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")) - numberOfProfileDirs := len(files) - - files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")) - numberOfMachineDirs := len(files) - - profileToDelete := "p8_partial_machine_config" - profile, _ := config.LoadProfile(profileToDelete) - - errs := DeleteProfiles([]*config.Profile{profile}) - - if len(errs) > 0 { - HandleDeletionErrors(errs) - t.Fatal("Errors while deleting profiles") - } - - pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) - } - - pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath()) - if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) { - t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name) - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) { - t.Fatal("Did not delete exactly one profile") - } - - if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != (numberOfMachineDirs - 1) { - t.Fatal("Did not delete exactly one profile") - } - - viper.Set(config.MachineProfile, "") } func TestDeleteAllProfiles(t *testing.T) { - const numberOfTotalProfileDirs = 8 - const numberOfTotalMachineDirs = 7 - - testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-all/.minikube" - miniDir, err := filepath.Abs(testMinikubeDir) - + td, err := ioutil.TempDir("", "all") if err != nil { - t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err) + t.Fatalf("tempdir: %v", err) + } + err = copy.Copy("../../../pkg/minikube/config/testdata/delete-all", td) + if err != nil { + t.Fatalf("copy: %v", err) } - err = os.Setenv(localpath.MinikubeHome, miniDir) + err = os.Setenv(localpath.MinikubeHome, td) if err != nil { t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome) } - files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")) - numberOfProfileDirs := len(files) - - files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")) - numberOfMachineDirs := len(files) - - if numberOfTotalProfileDirs != numberOfProfileDirs { - t.Error("invalid testdata") + pFiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles")) + if err != nil { + t.Errorf("filenames: %v", err) + } + mFiles, err := fileNames(filepath.Join(localpath.MiniPath(), "machines")) + if err != nil { + t.Errorf("filenames: %v", err) } - if numberOfTotalMachineDirs != numberOfMachineDirs { - t.Error("invalid testdata") + const numberOfTotalProfileDirs = 8 + if numberOfTotalProfileDirs != len(pFiles) { + t.Errorf("got %d test profiles, expected %d: %s", len(pFiles), numberOfTotalProfileDirs, pFiles) + } + const numberOfTotalMachineDirs = 7 + if numberOfTotalMachineDirs != len(mFiles) { + t.Errorf("got %d test machines, expected %d: %s", len(mFiles), numberOfTotalMachineDirs, mFiles) } validProfiles, inValidProfiles, err := config.ListProfiles() - if err != nil { t.Error(err) } if numberOfTotalProfileDirs != len(validProfiles)+len(inValidProfiles) { - t.Error("invalid testdata") + t.Errorf("ListProfiles length = %d, expected %d\nvalid: %v\ninvalid: %v\n", len(validProfiles)+len(inValidProfiles), numberOfTotalProfileDirs, validProfiles, inValidProfiles) } profiles := append(validProfiles, inValidProfiles...) @@ -475,18 +196,20 @@ func TestDeleteAllProfiles(t *testing.T) { t.Errorf("errors while deleting all profiles: %v", errs) } - files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")) - numberOfProfileDirs = len(files) - - files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")) - numberOfMachineDirs = len(files) - - if numberOfProfileDirs != 0 { - t.Errorf("Did not delete all profiles: still %d profiles left", numberOfProfileDirs) + afterProfiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles")) + if err != nil { + t.Errorf("profiles: %v", err) + } + afterMachines, err := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")) + if err != nil { + t.Errorf("machines: %v", err) + } + if len(afterProfiles) != 0 { + t.Errorf("Did not delete all profiles, remaining: %v", afterProfiles) } - if numberOfMachineDirs != 0 { - t.Errorf("Did not delete all profiles: still %d machines left", numberOfMachineDirs) + if len(afterMachines) != 0 { + t.Errorf("Did not delete all machines, remaining: %v", afterMachines) } viper.Set(config.MachineProfile, "") diff --git a/go.mod b/go.mod index 77e516b0be..ebb2c83a49 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,6 @@ require ( github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/google/go-cmp v0.3.0 - github.com/google/go-github/v25 v25.0.2 github.com/gorilla/mux v1.7.1 // indirect github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce // indirect github.com/hashicorp/go-getter v1.3.0 @@ -50,6 +49,7 @@ require ( github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936 github.com/moby/hyperkit v0.0.0-20171020124204-a12cd7250bcd github.com/olekukonko/tablewriter v0.0.0-20160923125401-bdcc175572fd + github.com/otiai10/copy v1.0.2 github.com/pborman/uuid v1.2.0 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/pkg/browser v0.0.0-20160118053552-9302be274faa @@ -69,7 +69,6 @@ require ( github.com/zchee/go-vmnet v0.0.0-20161021174912-97ebf9174097 golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 - golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a golang.org/x/sync v0.0.0-20190423024810-112230192c58 golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb golang.org/x/text v0.3.2 diff --git a/go.sum b/go.sum index cae562ed96..03c9eb6c9c 100644 --- a/go.sum +++ b/go.sum @@ -195,8 +195,6 @@ github.com/google/go-containerregistry v0.0.0-20180731221751-697ee0b3d46e h1:Hm0 github.com/google/go-containerregistry v0.0.0-20180731221751-697ee0b3d46e/go.mod h1:yZAFP63pRshzrEYLXLGPmUt0Ay+2zdjmMN1loCnRLUk= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-github/v25 v25.0.2 h1:MqXE7nOlIF91NJ/PXAcvS2dC+XXCDbY7RvJzjyEPAoU= -github.com/google/go-github/v25 v25.0.2/go.mod h1:6z5pC69qHtrPJ0sXPsj4BLnd82b+r6sLB7qcBoRZqpw= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= @@ -383,6 +381,11 @@ github.com/opencontainers/runc v0.0.0-20181113202123-f000fe11ece1/go.mod h1:qT5X github.com/opencontainers/runtime-spec v1.0.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v0.0.0-20170621221121-4a2974bf1ee9/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/otiai10/copy v1.0.2 h1:DDNipYy6RkIkjMwy+AWzgKiNTyj2RUI9yEMeETEpVyc= +github.com/otiai10/copy v1.0.2/go.mod h1:c7RpqBkwMom4bYTSkLSym4VSJz/XtncWRAj/J4PEIMY= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -558,7 +561,6 @@ golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5Tlb golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From 484a66e08216607e2a0f8c0ab62a773f7848ce0d Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Fri, 18 Oct 2019 16:55:58 -0700 Subject: [PATCH 63/78] Add skeleton for mkcmp This PR adds a skeleton for mkcmp, a binary to compare the performance of two versions of minikube. It adds a Makefile rule out/mkcmp which builds the binary. --- Makefile | 4 +++ cmd/performance/cmd/mkcmp.go | 48 ++++++++++++++++++++++++++++++++++++ cmd/performance/main.go | 20 +++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 cmd/performance/cmd/mkcmp.go create mode 100644 cmd/performance/main.go diff --git a/Makefile b/Makefile index f4efa1dfdb..7fab4a12bf 100755 --- a/Makefile +++ b/Makefile @@ -551,3 +551,7 @@ site: site/themes/docsy/assets/vendor/bootstrap/package.js out/hugo/hugo --navigateToChanged \ --ignoreCache \ --buildFuture) + +.PHONY: out/mkcmp +out/mkcmp: + GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o $@ cmd/performance/main.go diff --git a/cmd/performance/cmd/mkcmp.go b/cmd/performance/cmd/mkcmp.go new file mode 100644 index 0000000000..635113ad5d --- /dev/null +++ b/cmd/performance/cmd/mkcmp.go @@ -0,0 +1,48 @@ +/* +Copyright 2016 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 cmd + +import ( + "errors" + "fmt" + "os" + + "github.com/spf13/cobra" +) + +var rootCmd = &cobra.Command{ + Use: "mkcmp [path to first binary] [path to second binary]", + Short: "mkcmp is used to compare performance of two minikube binaries", + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + return validateArgs(args) + }, + Run: func(cmd *cobra.Command, args []string) { + return + }, +} + +func validateArgs(args []string) error { + if len(args) != 2 { + return errors.New("mkcmp requries two minikube binaries to compare: mkcmp [path to first binary] [path to second binary]") + } + return nil +} + +// Execute runs the mkcmp command +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} diff --git a/cmd/performance/main.go b/cmd/performance/main.go new file mode 100644 index 0000000000..f28a5e6559 --- /dev/null +++ b/cmd/performance/main.go @@ -0,0 +1,20 @@ +/* +Copyright 2016 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 main + +import "k8s.io/minikube/cmd/performance/cmd" + +func main() { + cmd.Execute() +} From 91b744095d976128c52cde1e0d6a5358f5192953 Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Fri, 18 Oct 2019 17:06:06 -0700 Subject: [PATCH 64/78] Fix boilerplate --- cmd/performance/cmd/mkcmp.go | 5 ++++- cmd/performance/main.go | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/cmd/performance/cmd/mkcmp.go b/cmd/performance/cmd/mkcmp.go index 635113ad5d..4594722758 100644 --- a/cmd/performance/cmd/mkcmp.go +++ b/cmd/performance/cmd/mkcmp.go @@ -1,9 +1,12 @@ /* -Copyright 2016 The Kubernetes Authors All rights reserved. +Copyright 2017 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. diff --git a/cmd/performance/main.go b/cmd/performance/main.go index f28a5e6559..82c0efb0ac 100644 --- a/cmd/performance/main.go +++ b/cmd/performance/main.go @@ -1,9 +1,12 @@ /* -Copyright 2016 The Kubernetes Authors All rights reserved. +Copyright 2017 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. From f2900c613eb67c1b487350e4e0416c6f3106f11f Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Fri, 18 Oct 2019 17:07:50 -0700 Subject: [PATCH 65/78] fix linting error --- cmd/performance/cmd/mkcmp.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmd/performance/cmd/mkcmp.go b/cmd/performance/cmd/mkcmp.go index 4594722758..f1a26fe953 100644 --- a/cmd/performance/cmd/mkcmp.go +++ b/cmd/performance/cmd/mkcmp.go @@ -30,14 +30,12 @@ var rootCmd = &cobra.Command{ PersistentPreRunE: func(cmd *cobra.Command, args []string) error { return validateArgs(args) }, - Run: func(cmd *cobra.Command, args []string) { - return - }, + Run: func(cmd *cobra.Command, args []string) {}, } func validateArgs(args []string) error { if len(args) != 2 { - return errors.New("mkcmp requries two minikube binaries to compare: mkcmp [path to first binary] [path to second binary]") + return errors.New("mkcmp requires two minikube binaries to compare: mkcmp [path to first binary] [path to second binary]") } return nil } From 73035dcec0e85fb6380bb87bc71d2ee266d38c16 Mon Sep 17 00:00:00 2001 From: Kenta Iso Date: Sat, 19 Oct 2019 16:09:06 +0900 Subject: [PATCH 66/78] fix test case ok kubeadm to download linux kubeadm binary --- pkg/minikube/machine/cache_binaries_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/minikube/machine/cache_binaries_test.go b/pkg/minikube/machine/cache_binaries_test.go index 6ccaf2e3f7..19bbb1fa2e 100644 --- a/pkg/minikube/machine/cache_binaries_test.go +++ b/pkg/minikube/machine/cache_binaries_test.go @@ -136,7 +136,7 @@ func TestCacheBinary(t *testing.T) { { desc: "ok kubeadm", version: "v1.16.0", - osName: runtime.GOOS, + osName: "linux", archName: runtime.GOARCH, binary: "kubeadm", err: false, From 76a8df226f84f329266e1c3d9a63d83e263e6d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20F=20Bj=C3=B6rklund?= Date: Sat, 19 Oct 2019 09:33:44 +0200 Subject: [PATCH 67/78] Remove duplication in make due to windows paths --- Makefile | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index f4efa1dfdb..c9e202a556 100755 --- a/Makefile +++ b/Makefile @@ -127,6 +127,12 @@ endif ifeq ($(GOOS),windows) IS_EXE = .exe + DIRSEP_ = \\ + DIRSEP = $(strip $(DIRSEP_)) + PATHSEP = ; +else + DIRSEP = / + PATHSEP = : endif @@ -239,28 +245,18 @@ extract: pkg/minikube/assets/assets.go: $(shell find "deploy/addons" -type f) ifeq ($(MINIKUBE_BUILD_IN_DOCKER),y) $(call DOCKER,$(BUILD_IMAGE),/usr/bin/make $@) -else ifeq ($(GOOS),windows) - which go-bindata || GO111MODULE=off GOBIN="$(GOPATH)\bin" go get github.com/jteeuwen/go-bindata/... - PATH="$(PATH);$(GOPATH)\bin" go-bindata -nomemcopy -o $@ -pkg assets deploy/addons/... - -gofmt -s -w $@ -else - which go-bindata || GO111MODULE=off GOBIN=$(GOPATH)/bin go get github.com/jteeuwen/go-bindata/... - PATH="$(PATH):$(GOPATH)/bin" go-bindata -nomemcopy -o $@ -pkg assets deploy/addons/... - -gofmt -s -w $@ endif + which go-bindata || GO111MODULE=off GOBIN="$(GOPATH)$(DIRSEP)bin" go get github.com/jteeuwen/go-bindata/... + PATH="$(PATH)$(PATHSEP)$(GOPATH)$(DIRSEP)bin" go-bindata -nomemcopy -o $@ -pkg assets deploy/addons/... + -gofmt -s -w $@ pkg/minikube/translate/translations.go: $(shell find "translations/" -type f) ifeq ($(MINIKUBE_BUILD_IN_DOCKER),y) $(call DOCKER,$(BUILD_IMAGE),/usr/bin/make $@) -else ifeq ($(GOOS),windows) - which go-bindata || GO111MODULE=off GOBIN="$(GOPATH)\bin" go get github.com/jteeuwen/go-bindata/... - PATH="$(PATH);$(GOPATH)\bin" go-bindata -nomemcopy -o $@ -pkg translate translations/... - -gofmt -s -w $@ -else - which go-bindata || GO111MODULE=off GOBIN=$(GOPATH)/bin go get github.com/jteeuwen/go-bindata/... - PATH="$(PATH):$(GOPATH)/bin" go-bindata -nomemcopy -o $@ -pkg translate translations/... - -gofmt -s -w $@ endif + which go-bindata || GO111MODULE=off GOBIN="$(GOPATH)$(DIRSEP)bin" go get github.com/jteeuwen/go-bindata/... + PATH="$(PATH)$(PATHSEP)$(GOPATH)$(DIRSEP)bin" go-bindata -nomemcopy -o $@ -pkg translate translations/... + -gofmt -s -w $@ @#golint: Json should be JSON (compat sed) @sed -i -e 's/Json/JSON/' $@ && rm -f ./-e From 96c39bf050f1930dd483d4d366666d8b16a55b1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20F=20Bj=C3=B6rklund?= Date: Sat, 19 Oct 2019 09:35:43 +0200 Subject: [PATCH 68/78] Pick some lint from the recent master commits --- Makefile | 4 +++- cmd/minikube/cmd/delete.go | 10 +++++++--- cmd/minikube/cmd/start.go | 1 + pkg/minikube/bootstrapper/images/images.go | 4 +++- pkg/minikube/cluster/cluster.go | 4 ++-- pkg/minikube/cluster/machine.go | 5 +++-- pkg/minikube/config/profile.go | 2 +- 7 files changed, 20 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index c9e202a556..76f24905e4 100755 --- a/Makefile +++ b/Makefile @@ -249,6 +249,8 @@ endif which go-bindata || GO111MODULE=off GOBIN="$(GOPATH)$(DIRSEP)bin" go get github.com/jteeuwen/go-bindata/... PATH="$(PATH)$(PATHSEP)$(GOPATH)$(DIRSEP)bin" go-bindata -nomemcopy -o $@ -pkg assets deploy/addons/... -gofmt -s -w $@ + @#golint: Dns should be DNS (compat sed) + @sed -i -e 's/Dns/DNS/g' $@ && rm -f ./-e pkg/minikube/translate/translations.go: $(shell find "translations/" -type f) ifeq ($(MINIKUBE_BUILD_IN_DOCKER),y) @@ -308,7 +310,7 @@ vet: @go vet $(SOURCE_PACKAGES) .PHONY: golint -golint: +golint: pkg/minikube/assets/assets.go pkg/minikube/translate/translations.go @golint -set_exit_status $(SOURCE_PACKAGES) .PHONY: gocyclo diff --git a/cmd/minikube/cmd/delete.go b/cmd/minikube/cmd/delete.go index a0b14ec63f..3bbd48df71 100644 --- a/cmd/minikube/cmd/delete.go +++ b/cmd/minikube/cmd/delete.go @@ -56,11 +56,15 @@ associated files.`, type typeOfError int const ( - Fatal typeOfError = 0 + // Fatal is a type of DeletionError + Fatal typeOfError = 0 + // MissingProfile is a type of DeletionError MissingProfile typeOfError = 1 + // MissingCluster is a type of DeletionError MissingCluster typeOfError = 2 ) +// DeletionError can be returned from DeleteProfiles type DeletionError struct { Err error Errtype typeOfError @@ -118,7 +122,7 @@ func runDelete(cmd *cobra.Command, args []string) { } } -// Deletes one or more profiles +// DeleteProfiles deletes one or more profiles func DeleteProfiles(profiles []*pkg_config.Profile) []error { var errs []error for _, profile := range profiles { @@ -246,7 +250,7 @@ func uninstallKubernetes(api libmachine.API, kc pkg_config.KubernetesConfig, bsN return nil } -// Handles deletion error from DeleteProfiles +// HandleDeletionErrors handles deletion errors from DeleteProfiles func HandleDeletionErrors(errors []error) { if len(errors) == 1 { handleSingleDeletionError(errors[0]) diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index 74eba46dcf..91a59131c9 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -137,6 +137,7 @@ type kubectlversion struct { SVersion VersionInfo `json:"serverVersion"` } +// VersionInfo holds version information type VersionInfo struct { Major string `json:"major"` Minor string `json:"minor"` diff --git a/pkg/minikube/bootstrapper/images/images.go b/pkg/minikube/bootstrapper/images/images.go index a8bc2b13e0..b69d1160bd 100644 --- a/pkg/minikube/bootstrapper/images/images.go +++ b/pkg/minikube/bootstrapper/images/images.go @@ -26,7 +26,9 @@ import ( ) const ( - DefaultImageRepo = "k8s.gcr.io" + // DefaultImageRepo is the default repository for images + DefaultImageRepo = "k8s.gcr.io" + // DefaultMinikubeRepo is the default repository for minikube DefaultMinikubeRepo = "gcr.io/k8s-minikube" ) diff --git a/pkg/minikube/cluster/cluster.go b/pkg/minikube/cluster/cluster.go index 7526daf324..7e3b611934 100644 --- a/pkg/minikube/cluster/cluster.go +++ b/pkg/minikube/cluster/cluster.go @@ -604,8 +604,8 @@ func CreateSSHShell(api libmachine.API, args []string) error { return client.Shell(args...) } -// EnsureMinikubeRunningOrExit checks that minikube has a status available and that -// the status is `Running`, otherwise it will exit +// IsMinikubeRunning checks that minikube has a status available and that +// the status is `Running` func IsMinikubeRunning(api libmachine.API) bool { s, err := GetHostStatus(api) if err != nil { diff --git a/pkg/minikube/cluster/machine.go b/pkg/minikube/cluster/machine.go index 8a24b04e3c..bb8e880389 100644 --- a/pkg/minikube/cluster/machine.go +++ b/pkg/minikube/cluster/machine.go @@ -26,6 +26,7 @@ import ( "k8s.io/minikube/pkg/minikube/machine" ) +// Machine contains information about a machine type Machine struct { *host.Host } @@ -58,7 +59,7 @@ func (h *Machine) IsValid() bool { return true } -// ListsMachines return all valid and invalid machines +// ListMachines return all valid and invalid machines // If a machine is valid or invalid is determined by the cluster.IsValid function func ListMachines(miniHome ...string) (validMachines []*Machine, inValidMachines []*Machine, err error) { pDirs, err := machineDirs(miniHome...) @@ -80,7 +81,7 @@ func ListMachines(miniHome ...string) (validMachines []*Machine, inValidMachines return validMachines, inValidMachines, nil } -// Loads a machine or throws an error if the machine could not be loadedG +// LoadMachine loads a machine or throws an error if the machine could not be loadedG func LoadMachine(name string) (*Machine, error) { api, err := machine.NewAPIClient() if err != nil { diff --git a/pkg/minikube/config/profile.go b/pkg/minikube/config/profile.go index 2c09f4b446..1ee1bff6f2 100644 --- a/pkg/minikube/config/profile.go +++ b/pkg/minikube/config/profile.go @@ -136,7 +136,7 @@ func ListProfiles(miniHome ...string) (validPs []*Profile, inValidPs []*Profile, return validPs, inValidPs, nil } -// loadProfile loads type Profile based on its name +// LoadProfile loads type Profile based on its name func LoadProfile(name string, miniHome ...string) (*Profile, error) { cfg, err := DefaultLoader.LoadConfigFromFile(name, miniHome...) p := &Profile{ From cba3b214421e701ccaff0fb10ccaa69a9ce810c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20F=20Bj=C3=B6rklund?= Date: Sat, 19 Oct 2019 13:20:27 +0200 Subject: [PATCH 69/78] toolbox: upgrade to latest fedora (currently 30) --- .../board/coreos/minikube/rootfs-overlay/usr/bin/toolbox | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/iso/minikube-iso/board/coreos/minikube/rootfs-overlay/usr/bin/toolbox b/deploy/iso/minikube-iso/board/coreos/minikube/rootfs-overlay/usr/bin/toolbox index bdfad1d3e9..6f22bccfa3 100644 --- a/deploy/iso/minikube-iso/board/coreos/minikube/rootfs-overlay/usr/bin/toolbox +++ b/deploy/iso/minikube-iso/board/coreos/minikube/rootfs-overlay/usr/bin/toolbox @@ -8,11 +8,11 @@ machine=$(uname -m) case ${machine} in aarch64 ) TOOLBOX_DOCKER_IMAGE=arm64v8/fedora - TOOLBOX_DOCKER_TAG=29 + TOOLBOX_DOCKER_TAG=latest ;; x86_64 ) TOOLBOX_DOCKER_IMAGE=fedora - TOOLBOX_DOCKER_TAG=29 + TOOLBOX_DOCKER_TAG=latest ;; * ) echo "Warning: Unknown machine type ${machine}" >&2 From 4b56526d66380444a2da35a4db4865489fea915a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20F=20Bj=C3=B6rklund?= Date: Sat, 19 Oct 2019 13:22:34 +0200 Subject: [PATCH 70/78] toolbox: support newer systemd-nspawn (232 and up) --- .../board/coreos/minikube/rootfs-overlay/usr/bin/toolbox | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/deploy/iso/minikube-iso/board/coreos/minikube/rootfs-overlay/usr/bin/toolbox b/deploy/iso/minikube-iso/board/coreos/minikube/rootfs-overlay/usr/bin/toolbox index 6f22bccfa3..2f597cd80b 100644 --- a/deploy/iso/minikube-iso/board/coreos/minikube/rootfs-overlay/usr/bin/toolbox +++ b/deploy/iso/minikube-iso/board/coreos/minikube/rootfs-overlay/usr/bin/toolbox @@ -69,10 +69,9 @@ if [ "x${1-}" == x-c ]; then set /bin/sh "$@" fi -sudo systemd-nspawn \ +sudo SYSTEMD_NSPAWN_SHARE_SYSTEM=1 systemd-nspawn \ --directory="${machinepath}" \ --capability=all \ - --share-system \ ${TOOLBOX_BIND} \ ${TOOLBOX_ENV} \ --user="${TOOLBOX_USER}" "$@" From a14bc57f64fc30685ef7e62eb3e24f668085846f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20F=20Bj=C3=B6rklund?= Date: Sat, 19 Oct 2019 17:54:33 +0200 Subject: [PATCH 71/78] Build minikube for arm64 (aarch64) as well This a pure build target, no test done (yet) No virtualization supported on this platform Adopt packaging to handle multiple arch, but don't package anything extra by default yet. --- Makefile | 44 +++++++++++++------ .../deb/minikube_deb_template/DEBIAN/control | 2 +- .../rpm/minikube_rpm_template/minikube.spec | 4 +- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index f4efa1dfdb..f5903e585d 100755 --- a/Makefile +++ b/Makefile @@ -130,14 +130,21 @@ ifeq ($(GOOS),windows) endif +out/minikube-linux-x86_64: out/minikube-linux-amd64 + cp $< $@ + +out/minikube-linux-aarch64: out/minikube-linux-arm64 + cp $< $@ + out/minikube$(IS_EXE): out/minikube-$(GOOS)-$(GOARCH)$(IS_EXE) cp $< $@ out/minikube-windows-amd64.exe: out/minikube-windows-amd64 cp $< $@ -.PHONY: minikube-linux-amd64 minikube-darwin-amd64 minikube-windows-amd64.exe +.PHONY: minikube-linux-amd64 minikube-linux-arm64 minikube-darwin-amd64 minikube-windows-amd64.exe minikube-linux-amd64: out/minikube-linux-amd64 +minikube-linux-arm64: out/minikube-linux-arm64 minikube-darwin-amd64: out/minikube-darwin-amd64 minikube-windows-amd64.exe: out/minikube-windows-amd64.exe @@ -265,7 +272,7 @@ endif @sed -i -e 's/Json/JSON/' $@ && rm -f ./-e .PHONY: cross -cross: minikube-linux-amd64 minikube-darwin-amd64 minikube-windows-amd64.exe +cross: minikube-linux-amd64 minikube-linux-arm64 minikube-darwin-amd64 minikube-windows-amd64.exe .PHONY: windows windows: minikube-windows-amd64.exe @@ -281,7 +288,8 @@ e2e-cross: e2e-linux-amd64 e2e-darwin-amd64 e2e-windows-amd64.exe .PHONY: checksum checksum: - for f in out/minikube-linux-amd64 out/minikube-darwin-amd64 out/minikube-windows-amd64.exe out/minikube.iso \ + for f in out/minikube.iso out/minikube-linux-amd64 minikube-linux-arm64 \ + out/minikube-darwin-amd64 out/minikube-windows-amd64.exe \ out/docker-machine-driver-kvm2 out/docker-machine-driver-hyperkit; do \ if [ -f "$${f}" ]; then \ openssl sha256 "$${f}" | awk '{print $$2}' > "$${f}.sha256" ; \ @@ -348,21 +356,29 @@ mdlint: out/docs/minikube.md: $(shell find "cmd") $(shell find "pkg/minikube/constants") pkg/minikube/assets/assets.go pkg/minikube/translate/translations.go go run -ldflags="$(MINIKUBE_LDFLAGS)" -tags gendocs hack/help_text/gen_help_text.go -out/minikube_$(DEB_VERSION).deb: out/minikube-linux-amd64 +out/minikube_$(DEB_VERSION).deb: out/minikube_$(DEB_VERSION)-0_amd64.deb + cp $< $@ + +out/minikube_$(DEB_VERSION)-0_%.deb: out/minikube-linux-% cp -r installers/linux/deb/minikube_deb_template out/minikube_$(DEB_VERSION) chmod 0755 out/minikube_$(DEB_VERSION)/DEBIAN sed -E -i 's/--VERSION--/'$(DEB_VERSION)'/g' out/minikube_$(DEB_VERSION)/DEBIAN/control + sed -E -i 's/--ARCH--/'$*'/g' out/minikube_$(DEB_VERSION)/DEBIAN/control mkdir -p out/minikube_$(DEB_VERSION)/usr/bin - cp out/minikube-linux-amd64 out/minikube_$(DEB_VERSION)/usr/bin/minikube - fakeroot dpkg-deb --build out/minikube_$(DEB_VERSION) + cp $< out/minikube_$(DEB_VERSION)/usr/bin/minikube + fakeroot dpkg-deb --build out/minikube_$(DEB_VERSION) $@ rm -rf out/minikube_$(DEB_VERSION) -out/minikube-$(RPM_VERSION).rpm: out/minikube-linux-amd64 +out/minikube-$(RPM_VERSION).rpm: out/minikube-$(RPM_VERSION)-0.x86_64.rpm + cp $< $@ + +out/minikube-$(RPM_VERSION)-0.%.rpm: out/minikube-linux-% cp -r installers/linux/rpm/minikube_rpm_template out/minikube-$(RPM_VERSION) sed -E -i 's/--VERSION--/'$(RPM_VERSION)'/g' out/minikube-$(RPM_VERSION)/minikube.spec sed -E -i 's|--OUT--|'$(PWD)/out'|g' out/minikube-$(RPM_VERSION)/minikube.spec - rpmbuild -bb -D "_rpmdir $(PWD)/out" -D "_rpmfilename minikube-$(RPM_VERSION).rpm" \ + rpmbuild -bb -D "_rpmdir $(PWD)/out" --target $* \ out/minikube-$(RPM_VERSION)/minikube.spec + @mv out/$*/minikube-$(RPM_VERSION)-0.$*.rpm out/ && rmdir out/$* rm -rf out/minikube-$(RPM_VERSION) .PHONY: apt @@ -380,14 +396,16 @@ out/repodata/repomd.xml: out/minikube-$(RPM_VERSION).rpm -u "$(MINIKUBE_RELEASES_URL)/$(VERSION)/" out .SECONDEXPANSION: -TAR_TARGETS_linux := out/minikube-linux-amd64 out/docker-machine-driver-kvm2 -TAR_TARGETS_darwin := out/minikube-darwin-amd64 out/docker-machine-driver-hyperkit -TAR_TARGETS_windows := out/minikube-windows-amd64.exe -out/minikube-%-amd64.tar.gz: $$(TAR_TARGETS_$$*) +TAR_TARGETS_linux-amd64 := out/minikube-linux-amd64 out/docker-machine-driver-kvm2 +TAR_TARGETS_linux-arm64 := out/minikube-linux-arm64 +TAR_TARGETS_darwin-amd64 := out/minikube-darwin-amd64 out/docker-machine-driver-hyperkit +TAR_TARGETS_windows-amd64 := out/minikube-windows-amd64.exe +out/minikube-%.tar.gz: $$(TAR_TARGETS_$$*) tar -cvzf $@ $^ .PHONY: cross-tars -cross-tars: out/minikube-windows-amd64.tar.gz out/minikube-linux-amd64.tar.gz out/minikube-darwin-amd64.tar.gz +cross-tars: out/minikube-linux-amd64.tar.gz out/minikube-linux-arm64.tar.gz \ + out/minikube-windows-amd64.tar.gz out/minikube-darwin-amd64.tar.gz -cd out && $(SHA512SUM) *.tar.gz > SHA512SUM out/minikube-installer.exe: out/minikube-windows-amd64.exe diff --git a/installers/linux/deb/minikube_deb_template/DEBIAN/control b/installers/linux/deb/minikube_deb_template/DEBIAN/control index 98a93a25b8..ad9d368ba0 100644 --- a/installers/linux/deb/minikube_deb_template/DEBIAN/control +++ b/installers/linux/deb/minikube_deb_template/DEBIAN/control @@ -2,7 +2,7 @@ Package: minikube Version: --VERSION-- Section: base Priority: optional -Architecture: amd64 +Architecture: --ARCH-- Recommends: virtualbox Maintainer: Thomas Strömberg Description: Minikube diff --git a/installers/linux/rpm/minikube_rpm_template/minikube.spec b/installers/linux/rpm/minikube_rpm_template/minikube.spec index 16adf43729..01868349ed 100644 --- a/installers/linux/rpm/minikube_rpm_template/minikube.spec +++ b/installers/linux/rpm/minikube_rpm_template/minikube.spec @@ -18,12 +18,12 @@ day-to-day. %prep mkdir -p %{name}-%{version} cd %{name}-%{version} -cp --OUT--/minikube-linux-amd64 . +cp --OUT--/minikube-linux-%{_arch} minikube %install cd %{name}-%{version} mkdir -p %{buildroot}%{_bindir} -install -m 755 minikube-linux-amd64 %{buildroot}%{_bindir}/%{name} +install -m 755 minikube %{buildroot}%{_bindir}/%{name} %files %{_bindir}/%{name} From 2ba9cb4c1a21d87663e6a62443e679b6668beb84 Mon Sep 17 00:00:00 2001 From: Pranav Jituri Date: Sun, 20 Oct 2019 02:19:18 +0530 Subject: [PATCH 72/78] refactoring for delete --- cmd/minikube/cmd/delete.go | 80 +++++++++++++++++++++------------ pkg/minikube/cluster/cluster.go | 14 ++++-- 2 files changed, 62 insertions(+), 32 deletions(-) diff --git a/cmd/minikube/cmd/delete.go b/cmd/minikube/cmd/delete.go index d7b3fdee2c..4ec9a25608 100644 --- a/cmd/minikube/cmd/delete.go +++ b/cmd/minikube/cmd/delete.go @@ -17,13 +17,11 @@ limitations under the License. package cmd import ( - "bufio" "fmt" "io/ioutil" "os" "path/filepath" "strconv" - "strings" "github.com/docker/machine/libmachine" "github.com/docker/machine/libmachine/mcnerror" @@ -45,7 +43,7 @@ import ( const ( purge = "purge" - noPrompt = "no-prompt" + forcedelete = "forcedelete" ) // deleteCmd represents the delete command @@ -59,7 +57,7 @@ associated files.`, func init() { deleteCmd.Flags().Bool(purge, false, "Set this flag to delete the '.minikube' folder from your user directory. This will prompt for confirmation.") - deleteCmd.Flags().Bool(noPrompt, false, "Set this flag so that there are no prompts.") + deleteCmd.Flags().Bool(forcedelete, false, "Set this flag to delete all configurations and profiles") if err := viper.BindPFlags(deleteCmd.Flags()); err != nil { exit.WithError("unable to bind flags", err) @@ -71,7 +69,46 @@ func runDelete(cmd *cobra.Command, args []string) { if len(args) > 0 { exit.UsageT("Usage: minikube delete") } - profile := viper.GetString(pkg_config.MachineProfile) + + validProfiles, _, err := pkg_config.ListProfiles() + + // Check if the purge flag has been set but the force flag hasn't been set in case there are multiple profiles to delete. + // If the following condition is not met, error out. + glog.Infof("%v", viper.IsSet(forcedelete)) + glog.Infof("%v", viper.GetBool(forcedelete)) + if err == nil && viper.GetBool(purge) && len(validProfiles) > 1 && !viper.GetBool(forcedelete) { + out.T(out.Embarrassed, "Multiple minikube profiles were found - ") + for _, p := range validProfiles { + out.T(out.Notice," - {{.profileName}}", out.V{"profileName":p.Name}) + } + out.T(out.Notice, "Please use the {{.forceFlag}} to delete all of the configuration and the profiles.", out.V{"forceFlag":forcedelete}) + return + } + + // Perform all the procedure for each of the profiles which are available. + // For example, what if there are multiple profiles with multiple clusters running? + for _, p := range validProfiles { + deleteProfile(p.Name) + } + + // If the purge flag is set, go ahead and delete the .minikube directory. + if viper.GetBool(purge) { + glog.Infof("Purging the '.minikube' directory located at %s", localpath.MiniPath()) + if err := os.RemoveAll(localpath.MiniPath()); err != nil { + exit.WithError("unable to delete minikube config folder", err) + } + out.T(out.Crushed, "Successfully purged minikube directory located at - [{{.minikubeDirectory}}]", out.V{"minikubeDirectory":localpath.MiniPath()}) + } +} + +func deleteProfile (profile string) { + glog.Infof("Setting current profile to -- %v", profile) + err := cmdcfg.Set(pkg_config.MachineProfile, profile) + if err != nil { + exit.WithError("Setting profile failed", err) + } + glog.Infof("Successfully set profile to -- %v", profile) + api, err := machine.NewAPIClient() if err != nil { exit.WithError("Error getting client", err) @@ -122,30 +159,6 @@ func runDelete(cmd *cobra.Command, args []string) { if err := cmdcfg.Unset(pkg_config.MachineProfile); err != nil { exit.WithError("unset minikube profile", err) } - - // Delete the .minikube folder if the flags are set - if viper.GetBool(purge) { - glog.Infof("Purging the '.minikube' directory located at %s", localpath.MiniPath()) - - if viper.GetBool(noPrompt) { - glog.Infof("Will not prompt for deletion.") - } else { - out.T(out.Check, "Are you sure you want to delete the directory located at {{.minikubePath}}? This will delete all your configuration data related to minikube. (Y/N)", out.V{"minikubePath": localpath.MiniPath()}) - userInput := bufio.NewScanner(os.Stdin) - userInput.Scan() - var choice = userInput.Text() - if strings.ToLower(choice) != "y" { - out.T(out.Meh, "Not deleting minikube directory located at {{.minikubePath}}", out.V{"minikubePath": localpath.MiniPath()}) - return - } - } - if err := os.RemoveAll(localpath.MiniPath()); err != nil { - exit.WithError("unable to delete minikube config folder", err) - } - out.T(out.Crushed, "Deleted the {{.minikubePath}} folder successfully!", out.V{"minikubePath": localpath.MiniPath()}) - } else { - out.T(out.Meh, "Not deleting minikube directory located at {{.minikubePath}}", out.V{"minikubePath": localpath.MiniPath()}) - } } func uninstallKubernetes(api libmachine.API, kc pkg_config.KubernetesConfig, bsName string) { @@ -167,6 +180,15 @@ func deleteProfileDirectory(profile string) { exit.WithError("Unable to remove machine directory: %v", err) } } + + profileDir := filepath.Join(localpath.MiniPath(), "profiles", profile) + if _, err := os.Stat(profileDir); err == nil { + out.T(out.DeletingHost, `Removing {{.directory}} ...`, out.V{"directory": profileDir}) + err := os.RemoveAll(profileDir) + if err != nil { + exit.WithError("Unable to remove machine directory: %v", err) + } + } } // killMountProcess kills the mount process, if it is running diff --git a/pkg/minikube/cluster/cluster.go b/pkg/minikube/cluster/cluster.go index 96f8e45b7a..5f8fe185a9 100644 --- a/pkg/minikube/cluster/cluster.go +++ b/pkg/minikube/cluster/cluster.go @@ -270,14 +270,18 @@ func StopHost(api libmachine.API) error { // DeleteHost deletes the host VM. func DeleteHost(api libmachine.API) error { - host, err := api.Load(cfg.GetMachineName()) + out.T(out.DeletingHost,"0 {{.err}}", out.V{"err":cfg.GetMachineName()}) + host, err := api.Load(cfg.MachineProfile) + if err != nil { + out.T(out.DeletingHost,"1 {{.err}}", out.V{"err":err}) return errors.Wrap(err, "load") } - + out.T(out.DeletingHost, "Successfully powered off Hyper-V. minikube driver -- {{.driver}}", out.V{"driver": host.Driver.DriverName()}) // Get the status of the host. Ensure that it exists before proceeding ahead. status, err := GetHostStatus(api) if err != nil { + out.T(out.DeletingHost,"2 {{.err}}", out.V{"err":err}) exit.WithCodeT(exit.Failure, "Unable to get the status of the cluster.") } if status == state.None.String() { @@ -285,10 +289,14 @@ func DeleteHost(api libmachine.API) error { } // This is slow if SSH is not responding, but HyperV hangs otherwise, See issue #2914 - if host.Driver.DriverName() == constants.DriverHyperv { + if host.DriverName == constants.DriverHyperv { + out.T(out.DeletingHost, "3 {{.driver}}", out.V{"driver": host.Driver.DriverName()}) + out.T(out.DeletingHost, "4 {{.driver}}", out.V{"driver": host.DriverName}) if err := trySSHPowerOff(host); err != nil { glog.Infof("Unable to power off minikube because the host was not found.") + out.T(out.DeletingHost,"3 {{.err}}", out.V{"err":err}) } + out.T(out.DeletingHost, "Successfully powered off Hyper-V. minikube driver -- {{.driver}}", out.V{"driver": host.Driver.DriverName()}) } out.T(out.DeletingHost, `Deleting "{{.profile_name}}" in {{.driver_name}} ...`, out.V{"profile_name": cfg.GetMachineName(), "driver_name": host.DriverName}) From b3ccd9ae469aabdb867c37a979433f9d2179c0f4 Mon Sep 17 00:00:00 2001 From: Pranav Jituri Date: Sun, 20 Oct 2019 13:13:35 +0530 Subject: [PATCH 73/78] Refactored Delete and fixed linting issues --- cmd/minikube/cmd/delete.go | 43 ++++++++++++++------------- pkg/minikube/drivers/hyperv/driver.go | 4 +-- pkg/minikube/tunnel/route_windows.go | 2 +- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/cmd/minikube/cmd/delete.go b/cmd/minikube/cmd/delete.go index 6474f34dfb..5d2f4f9bb0 100644 --- a/cmd/minikube/cmd/delete.go +++ b/cmd/minikube/cmd/delete.go @@ -25,7 +25,7 @@ import ( "github.com/docker/machine/libmachine/mcnerror" "github.com/golang/glog" - ps "github.com/mitchellh/go-ps" + "github.com/mitchellh/go-ps" "github.com/pkg/errors" "github.com/docker/machine/libmachine" @@ -43,11 +43,7 @@ import ( ) var deleteAll bool - -const ( - purge = "purge" - forcedelete = "forcedelete" -) +var purge bool // deleteCmd represents the delete command var deleteCmd = &cobra.Command{ @@ -76,12 +72,13 @@ func (error DeletionError) Error() string { } func init() { - deleteCmd.Flags().Bool(purge, false, "Set this flag to delete the '.minikube' folder from your user directory. This will prompt for confirmation.") - deleteCmd.Flags().Bool(forcedelete, false, "Set this flag to delete all configurations and profiles") + deleteCmd.Flags().BoolVar(&deleteAll, "all", false, "Set flag to delete all profiles") + deleteCmd.Flags().BoolVar(&purge, "purge", false, "Set this flag to delete the '.minikube' folder from your user directory.") if err := viper.BindPFlags(deleteCmd.Flags()); err != nil { exit.WithError("unable to bind flags", err) } + RootCmd.AddCommand(deleteCmd) } // runDelete handles the executes the flow of "minikube delete" @@ -94,13 +91,16 @@ func runDelete(cmd *cobra.Command, args []string) { exit.WithError("Could not get profile flag", err) } + validProfiles, invalidProfiles, err := pkg_config.ListProfiles() + profilesToDelete := append(validProfiles, invalidProfiles...) + // If the purge flag is set, go ahead and delete the .minikube directory. - if viper.GetBool(purge) { - glog.Infof("Purging the '.minikube' directory located at %s", localpath.MiniPath()) - if err := os.RemoveAll(localpath.MiniPath()); err != nil { - exit.WithError("unable to delete minikube config folder", err) + if purge && len(profilesToDelete) > 1 && !deleteAll { + out.ErrT(out.Notice, "Multiple minikube profiles were found - ") + for _, p := range profilesToDelete { + out.T(out.Notice, " - {{.profile}}", out.V{"profile": p.Name}) } - out.T(out.Crushed, "Successfully purged minikube directory located at - [{{.minikubeDirectory}}]", out.V{"minikubeDirectory":localpath.MiniPath()}) + exit.UsageT("Usage: minikube delete --all --purge") } if deleteAll { @@ -108,9 +108,6 @@ func runDelete(cmd *cobra.Command, args []string) { exit.UsageT("usage: minikube delete --all") } - validProfiles, invalidProfiles, err := pkg_config.ListProfiles() - profilesToDelete := append(validProfiles, invalidProfiles...) - if err != nil { exit.WithError("Error getting profiles to delete", err) } @@ -139,6 +136,15 @@ func runDelete(cmd *cobra.Command, args []string) { out.T(out.DeletingHost, "Successfully deleted profile \"{{.name}}\"", out.V{"name": profileName}) } } + + // If the purge flag is set, go ahead and delete the .minikube directory. + if purge { + glog.Infof("Purging the '.minikube' directory located at %s", localpath.MiniPath()) + if err := os.RemoveAll(localpath.MiniPath()); err != nil { + exit.WithError("unable to delete minikube config folder", err) + } + out.T(out.Crushed, "Successfully purged minikube directory located at - [{{.minikubeDirectory}}]", out.V{"minikubeDirectory": localpath.MiniPath()}) + } } // Deletes one or more profiles @@ -369,8 +375,3 @@ func killMountProcess() error { } return nil } - -func init() { - deleteCmd.Flags().BoolVar(&deleteAll, "all", false, "Set flag to delete all profiles") - RootCmd.AddCommand(deleteCmd) -} diff --git a/pkg/minikube/drivers/hyperv/driver.go b/pkg/minikube/drivers/hyperv/driver.go index 00b7543351..8070737a3c 100644 --- a/pkg/minikube/drivers/hyperv/driver.go +++ b/pkg/minikube/drivers/hyperv/driver.go @@ -28,7 +28,7 @@ import ( ) func init() { - registry.Register(registry.DriverDef{ + _ = registry.Register(registry.DriverDef{ Name: constants.DriverHyperv, Builtin: true, ConfigCreator: createHypervHost, @@ -45,7 +45,7 @@ func createHypervHost(config cfg.MachineConfig) interface{} { d.VSwitch = config.HypervVirtualSwitch d.MemSize = config.Memory d.CPU = config.CPUs - d.DiskSize = int(config.DiskSize) + d.DiskSize = config.DiskSize d.SSHUser = "docker" d.DisableDynamicMemory = true // default to disable dynamic memory as minikube is unlikely to work properly with dynamic memory diff --git a/pkg/minikube/tunnel/route_windows.go b/pkg/minikube/tunnel/route_windows.go index 757074f190..0d561b3c1c 100644 --- a/pkg/minikube/tunnel/route_windows.go +++ b/pkg/minikube/tunnel/route_windows.go @@ -93,7 +93,7 @@ func (router *osRouter) parseTable(table []byte) routingTable { }, line: line, } - glog.V(4).Infof("adding line %s", tableLine) + glog.V(4).Infof("adding line %v", tableLine) t = append(t, tableLine) } } From 3ff4c442203933d704c6baa5250aa74b4aa2464e Mon Sep 17 00:00:00 2001 From: Pranav Jituri Date: Sun, 20 Oct 2019 13:24:15 +0530 Subject: [PATCH 74/78] Added delete command documentation --- .../en/docs/Reference/Commands/delete.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/site/content/en/docs/Reference/Commands/delete.md b/site/content/en/docs/Reference/Commands/delete.md index db3e2f7125..eabf82953a 100644 --- a/site/content/en/docs/Reference/Commands/delete.md +++ b/site/content/en/docs/Reference/Commands/delete.md @@ -18,6 +18,30 @@ associated files. minikube delete [flags] ``` +##### Delete all profiles +``` +minikube delete --all +``` + +##### Delete profile & `.minikube` directory +Do note that the following command only works if you have only 1 profile. If there are multiple profiles, the command will error out. +``` +minikube delete --purge +``` + +##### Delete all profiles & `.minikube` directory +This will delete all the profiles and `.minikube` directory. +``` +minikube delete --purge --all +``` + +### Flags + +``` + --all: Set flag to delete all profiles + --purge: Set this flag to delete the '.minikube' folder from your user directory. +``` + ### Options inherited from parent commands ``` From d411617f9c744fd410353fca43499254fafb419d Mon Sep 17 00:00:00 2001 From: cueo Date: Sun, 20 Oct 2019 19:11:26 +0530 Subject: [PATCH 75/78] Use opposite operator --- cmd/minikube/cmd/config/prompt.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/minikube/cmd/config/prompt.go b/cmd/minikube/cmd/config/prompt.go index 1577afc10c..10c00a7f0f 100644 --- a/cmd/minikube/cmd/config/prompt.go +++ b/cmd/minikube/cmd/config/prompt.go @@ -151,5 +151,5 @@ func posString(slice []string, element string) int { // containsString returns true if slice contains element func containsString(slice []string, element string) bool { - return !(posString(slice, element) == -1) + return posString(slice, element) != -1 } From 6533d9f2e8ac82ae9ab6fffe1af2249081e18f6b Mon Sep 17 00:00:00 2001 From: cueo Date: Sun, 20 Oct 2019 19:11:31 +0530 Subject: [PATCH 76/78] Rename methods to match the convention --- pkg/drivers/kvm/network_test.go | 2 +- pkg/minikube/config/config_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/drivers/kvm/network_test.go b/pkg/drivers/kvm/network_test.go index 985ac7f26e..905816165a 100644 --- a/pkg/drivers/kvm/network_test.go +++ b/pkg/drivers/kvm/network_test.go @@ -46,7 +46,7 @@ var ( ]`) ) -func Test_parseStatusAndReturnIp(t *testing.T) { +func TestParseStatusAndReturnIp(t *testing.T) { type args struct { mac string statuses []byte diff --git a/pkg/minikube/config/config_test.go b/pkg/minikube/config/config_test.go index b2671628df..20334aaa54 100644 --- a/pkg/minikube/config/config_test.go +++ b/pkg/minikube/config/config_test.go @@ -174,7 +174,7 @@ func TestWriteConfig(t *testing.T) { } } -func Test_encode(t *testing.T) { +func TestEncode(t *testing.T) { var b bytes.Buffer for _, tt := range configTestCases { err := encode(&b, tt.config) From a41ac45fcc297c1e8f3e3ea4a85a66f4b4cfbaf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20F=20Bj=C3=B6rklund?= Date: Sun, 20 Oct 2019 16:06:25 +0200 Subject: [PATCH 77/78] Add missing dash before the image arch This character (-) was removed by mistake, in 5fa6714 It is supposed to be "" for amd64, "-arm64" for arm64. --- pkg/minikube/assets/addons.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/minikube/assets/addons.go b/pkg/minikube/assets/addons.go index 18cfd22251..82bc8c1bd0 100644 --- a/pkg/minikube/assets/addons.go +++ b/pkg/minikube/assets/addons.go @@ -420,7 +420,7 @@ func GenerateTemplateData(cfg config.KubernetesConfig) interface{} { // for less common architectures blank suffix for amd64 ea := "" if runtime.GOARCH != "amd64" { - ea = runtime.GOARCH + ea = "-" + runtime.GOARCH } opts := struct { Arch string From 3f4bd388813b0640c17064a48b0f941b28fe9991 Mon Sep 17 00:00:00 2001 From: tanjunchen <2799194073@qq.com> Date: Mon, 21 Oct 2019 18:24:45 +0800 Subject: [PATCH 78/78] upgrade go version 1.12.9 -> 1.12.12 --- .travis.yml | 6 +++--- Makefile | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index acdc98cf0e..39089ee150 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ os: linux language: go go: - - 1.12.9 + - 1.12.12 env: global: - GOPROXY=https://proxy.golang.org @@ -19,7 +19,7 @@ matrix: - language: go name: Code Lint - go: 1.12.9 + go: 1.12.12 env: - TESTSUITE=lint before_install: @@ -28,7 +28,7 @@ matrix: - language: go name: Unit Test - go: 1.12.9 + go: 1.12.12 env: - TESTSUITE=unittest before_install: diff --git a/Makefile b/Makefile index f4efa1dfdb..b3a3e14627 100755 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ DEB_VERSION ?= $(subst -,~,$(RAW_VERSION)) RPM_VERSION ?= $(DEB_VERSION) # used by hack/jenkins/release_build_and_upload.sh and KVM_BUILD_IMAGE, see also BUILD_IMAGE below -GO_VERSION ?= 1.12.9 +GO_VERSION ?= 1.12.12 INSTALL_SIZE ?= $(shell du out/minikube-windows-amd64.exe | cut -f1) BUILDROOT_BRANCH ?= 2019.02.6