From 5f65dc80fab1750d67973178cdf73fc7faf826a5 Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Wed, 13 Feb 2019 12:37:44 -0800 Subject: [PATCH] Remove error uploads, consolidate fatal error handling into exit package --- cmd/minikube/cmd/cache.go | 16 +-- cmd/minikube/cmd/cache_list.go | 14 +-- cmd/minikube/cmd/completion.go | 13 +-- cmd/minikube/cmd/config/addons_list.go | 15 +-- cmd/minikube/cmd/config/config_view.go | 12 +- cmd/minikube/cmd/config/configure.go | 5 +- cmd/minikube/cmd/config/disable.go | 9 +- cmd/minikube/cmd/config/enable.go | 6 +- cmd/minikube/cmd/config/open.go | 28 ++--- cmd/minikube/cmd/config/profile.go | 9 +- cmd/minikube/cmd/config/set.go | 10 +- cmd/minikube/cmd/config/unset.go | 9 +- cmd/minikube/cmd/config/util.go | 5 +- cmd/minikube/cmd/dashboard.go | 16 +-- cmd/minikube/cmd/delete.go | 13 +-- cmd/minikube/cmd/env.go | 22 ++-- cmd/minikube/cmd/ip.go | 20 ++-- cmd/minikube/cmd/logs.go | 12 +- cmd/minikube/cmd/mount.go | 39 +++---- cmd/minikube/cmd/root.go | 6 +- cmd/minikube/cmd/service.go | 15 +-- cmd/minikube/cmd/service_list.go | 6 +- cmd/minikube/cmd/ssh.go | 16 +-- cmd/minikube/cmd/start.go | 73 +++++------- cmd/minikube/cmd/status.go | 30 ++--- cmd/minikube/cmd/stop.go | 10 +- cmd/minikube/cmd/tunnel.go | 9 +- cmd/minikube/cmd/update-check.go | 9 +- cmd/minikube/cmd/update-context.go | 14 +-- cmd/util/util.go | 156 +------------------------ cmd/util/util_test.go | 65 +---------- pkg/drivers/none/none.go | 4 +- pkg/minikube/cluster/cluster.go | 12 +- pkg/minikube/console/style.go | 2 + pkg/minikube/machine/client.go | 9 +- 35 files changed, 186 insertions(+), 523 deletions(-) diff --git a/cmd/minikube/cmd/cache.go b/cmd/minikube/cmd/cache.go index b30649d0c0..b6fdb246ca 100644 --- a/cmd/minikube/cmd/cache.go +++ b/cmd/minikube/cmd/cache.go @@ -17,13 +17,11 @@ limitations under the License. package cmd import ( - "os" - "github.com/spf13/cobra" cmdConfig "k8s.io/minikube/cmd/minikube/cmd/config" "k8s.io/minikube/pkg/minikube/config" - "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" ) @@ -42,13 +40,11 @@ var addCacheCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { // Cache and load images into docker daemon if err := machine.CacheAndLoadImages(args); err != nil { - console.Fatal("Failed to cache and load images: %v", err) - os.Exit(1) + exit.WithError("Failed to cache and load images", err) } // Add images to config file if err := cmdConfig.AddToConfigMap(constants.Cache, args); err != nil { - console.Fatal("Failed to update config: %v", err) - os.Exit(1) + exit.WithError("Failed to update config", err) } }, } @@ -61,13 +57,11 @@ var deleteCacheCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { // Delete images from config file if err := cmdConfig.DeleteFromConfigMap(constants.Cache, args); err != nil { - console.Fatal("Failed to delete images from config: %v", err) - os.Exit(1) + exit.WithError("Failed to delete images from config", err) } // Delete images from cache/images directory if err := machine.DeleteFromImageCacheDir(args); err != nil { - console.Fatal("Failed to delete images: %v", err) - os.Exit(1) + exit.WithError("Failed to delete images", err) } }, } diff --git a/cmd/minikube/cmd/cache_list.go b/cmd/minikube/cmd/cache_list.go index 92dc05601a..a181af1f18 100644 --- a/cmd/minikube/cmd/cache_list.go +++ b/cmd/minikube/cmd/cache_list.go @@ -22,8 +22,8 @@ import ( "github.com/spf13/cobra" cmdConfig "k8s.io/minikube/cmd/minikube/cmd/config" - "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/exit" ) var cacheListFormat string @@ -40,12 +40,10 @@ var listCacheCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { images, err := cmdConfig.ListConfigMap(constants.Cache) if err != nil { - console.Fatal("Failed to get image map: %v", err) - os.Exit(1) + exit.WithError("Failed to get image map", err) } if err := cacheList(images); err != nil { - console.Fatal("Failed to list cached images: %v", err) - os.Exit(1) + exit.WithError("Failed to list cached images", err) } }, } @@ -61,14 +59,12 @@ func cacheList(images []string) error { for _, image := range images { tmpl, err := template.New("list").Parse(cacheListFormat) if err != nil { - console.Fatal("Unable to parse template: %v", err) - os.Exit(1) + exit.WithError("Unable to parse template", err) } listTmplt := CacheListTemplate{image} err = tmpl.Execute(os.Stdout, listTmplt) if err != nil { - console.Fatal("Unable to process template: %v", err) - os.Exit(1) + exit.WithError("Unable to process template", err) } } return nil diff --git a/cmd/minikube/cmd/completion.go b/cmd/minikube/cmd/completion.go index 074e35b526..14b10e74ae 100644 --- a/cmd/minikube/cmd/completion.go +++ b/cmd/minikube/cmd/completion.go @@ -23,8 +23,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" - cmdutil "k8s.io/minikube/cmd/util" - "k8s.io/minikube/pkg/minikube/console" + "k8s.io/minikube/pkg/minikube/exit" ) const longDescription = ` @@ -70,21 +69,19 @@ var completionCmd = &cobra.Command{ Long: longDescription, Run: func(cmd *cobra.Command, args []string) { if len(args) != 1 { - console.ErrStyle("usage", "Usage: minikube completion SHELL") - os.Exit(1) + exit.Usage("Usage: minikube completion SHELL") } if args[0] != "bash" && args[0] != "zsh" { - console.Fatal("Sorry, completion support is not yet implemented for %q", args[0]) - os.Exit(1) + exit.Usage("Sorry, completion support is not yet implemented for %q", args[0]) } else if args[0] == "bash" { err := GenerateBashCompletion(os.Stdout, cmd.Parent()) if err != nil { - cmdutil.MaybeReportErrorAndExit(err) + exit.WithError("bash completion failed", err) } } else { err := GenerateZshCompletion(os.Stdout, cmd.Parent()) if err != nil { - cmdutil.MaybeReportErrorAndExit(err) + exit.WithError("zsh completion failed", err) } } diff --git a/cmd/minikube/cmd/config/addons_list.go b/cmd/minikube/cmd/config/addons_list.go index 51295ab106..00374dfe75 100644 --- a/cmd/minikube/cmd/config/addons_list.go +++ b/cmd/minikube/cmd/config/addons_list.go @@ -21,11 +21,10 @@ import ( "sort" "text/template" - "github.com/golang/glog" "github.com/spf13/cobra" "k8s.io/minikube/pkg/minikube/assets" - "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/exit" ) var addonListFormat string @@ -41,13 +40,11 @@ var addonsListCmd = &cobra.Command{ Long: "Lists all available minikube addons as well as their current statuses (enabled/disabled)", Run: func(cmd *cobra.Command, args []string) { if len(args) != 0 { - console.ErrStyle("usage", "usage: minikube addons list") - os.Exit(1) + exit.Usage("usage: minikube addons list") } err := addonList() if err != nil { - console.Fatal("addon list failed: %v", err) - os.Exit(1) + exit.WithError("addon list failed", err) } }, } @@ -81,14 +78,12 @@ func addonList() error { } tmpl, err := template.New("list").Parse(addonListFormat) if err != nil { - glog.Errorln("Error creating list template:", err) - os.Exit(1) + exit.WithError("Error creating list template", err) } listTmplt := AddonListTemplate{addonName, stringFromStatus(addonStatus)} err = tmpl.Execute(os.Stdout, listTmplt) if err != nil { - glog.Errorln("Error executing list template:", err) - os.Exit(1) + exit.WithError("Error executing list template", err) } } return nil diff --git a/cmd/minikube/cmd/config/config_view.go b/cmd/minikube/cmd/config/config_view.go index 90aa5f1368..013bd26fc5 100644 --- a/cmd/minikube/cmd/config/config_view.go +++ b/cmd/minikube/cmd/config/config_view.go @@ -20,11 +20,10 @@ import ( "os" "text/template" - "github.com/golang/glog" "github.com/spf13/cobra" "k8s.io/minikube/pkg/minikube/config" - "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/exit" ) var configViewFormat string @@ -41,8 +40,7 @@ var configViewCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { err := configView() if err != nil { - console.Fatal("config view failed: %v", err) - os.Exit(1) + exit.WithError("config view failed", err) } }, } @@ -62,14 +60,12 @@ func configView() error { for k, v := range cfg { tmpl, err := template.New("view").Parse(configViewFormat) if err != nil { - glog.Errorln("Error creating view template:", err) - os.Exit(1) + exit.WithError("Error creating view template", err) } viewTmplt := ConfigViewTemplate{k, v} err = tmpl.Execute(os.Stdout, viewTmplt) if err != nil { - glog.Errorln("Error executing view template:", err) - os.Exit(1) + exit.WithError("Error executing view template", err) } } return nil diff --git a/cmd/minikube/cmd/config/configure.go b/cmd/minikube/cmd/config/configure.go index 0cd20db864..43ba2a04e1 100644 --- a/cmd/minikube/cmd/config/configure.go +++ b/cmd/minikube/cmd/config/configure.go @@ -18,10 +18,10 @@ package config import ( "io/ioutil" - "os" "github.com/spf13/cobra" "k8s.io/minikube/pkg/minikube/console" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/service" ) @@ -31,8 +31,7 @@ var addonsConfigureCmd = &cobra.Command{ Long: "Configures the addon w/ADDON_NAME within minikube (example: minikube addons configure registry-creds). For a list of available addons use: minikube addons list ", Run: func(cmd *cobra.Command, args []string) { if len(args) != 1 { - console.ErrStyle("usage", "usage: minikube addons configure ADDON_NAME") - os.Exit(1) + exit.Usage("usage: minikube addons configure ADDON_NAME") } addon := args[0] diff --git a/cmd/minikube/cmd/config/disable.go b/cmd/minikube/cmd/config/disable.go index 0a36e8a028..ffabc863f0 100644 --- a/cmd/minikube/cmd/config/disable.go +++ b/cmd/minikube/cmd/config/disable.go @@ -17,10 +17,9 @@ limitations under the License. package config import ( - "os" - "github.com/spf13/cobra" "k8s.io/minikube/pkg/minikube/console" + "k8s.io/minikube/pkg/minikube/exit" ) var addonsDisableCmd = &cobra.Command{ @@ -29,15 +28,13 @@ var addonsDisableCmd = &cobra.Command{ Long: "Disables the addon w/ADDON_NAME within minikube (example: minikube addons disable dashboard). For a list of available addons use: minikube addons list ", Run: func(cmd *cobra.Command, args []string) { if len(args) != 1 { - console.ErrStyle("usage", "usage: minikube addons disable ADDON_NAME") - os.Exit(1) + exit.Usage("usage: minikube addons disable ADDON_NAME") } addon := args[0] err := Set(addon, "false") if err != nil { - console.Fatal("disable failed: %v", err) - os.Exit(1) + exit.WithError("disable failed", err) } console.Success("%s was successfully disabled", addon) }, diff --git a/cmd/minikube/cmd/config/enable.go b/cmd/minikube/cmd/config/enable.go index e6f41eb373..012bb9a5a1 100644 --- a/cmd/minikube/cmd/config/enable.go +++ b/cmd/minikube/cmd/config/enable.go @@ -17,10 +17,9 @@ limitations under the License. package config import ( - "os" - "github.com/spf13/cobra" "k8s.io/minikube/pkg/minikube/console" + "k8s.io/minikube/pkg/minikube/exit" ) var addonsEnableCmd = &cobra.Command{ @@ -29,8 +28,7 @@ var addonsEnableCmd = &cobra.Command{ Long: "Enables the addon w/ADDON_NAME within minikube (example: minikube addons enable dashboard). For a list of available addons use: minikube addons list ", Run: func(cmd *cobra.Command, args []string) { if len(args) != 1 { - console.ErrStyle("usage", "usage: minikube addons enable ADDON_NAME") - os.Exit(1) + exit.Usage("usage: minikube addons enable ADDON_NAME") } addon := args[0] diff --git a/cmd/minikube/cmd/config/open.go b/cmd/minikube/cmd/config/open.go index fe5d5c22c1..0c089bc4d3 100644 --- a/cmd/minikube/cmd/config/open.go +++ b/cmd/minikube/cmd/config/open.go @@ -25,6 +25,7 @@ import ( "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/service" ) @@ -47,43 +48,38 @@ var addonsOpenCmd = &cobra.Command{ PreRun: func(cmd *cobra.Command, args []string) { t, err := template.New("addonsURL").Parse(addonsURLFormat) if err != nil { - console.Fatal("The value passed to --format is invalid: %s", err) - os.Exit(1) + exit.Usage("The value passed to --format is invalid: %s", err) } addonsURLTemplate = t }, Run: func(cmd *cobra.Command, args []string) { if len(args) != 1 { - console.ErrStyle("usage", "usage: minikube addons open ADDON_NAME") - os.Exit(1) + exit.Usage("usage: minikube addons open ADDON_NAME") } addonName := args[0] //TODO(r2d4): config should not reference API, pull this out api, err := machine.NewAPIClient() if err != nil { - console.Fatal("Error getting client: %v", err) - os.Exit(1) + exit.WithError("Error getting client", err) } defer api.Close() cluster.EnsureMinikubeRunningOrExit(api, 1) addon, ok := assets.Addons[addonName] // validate addon input if !ok { - console.Fatal(`addon '%s' is not a valid addon packaged with minikube. + exit.WithCode(exit.Data, `addon '%s' is not a valid addon packaged with minikube. To see the list of available addons run: minikube addons list`, addonName) - os.Exit(1) } ok, err = addon.IsEnabled() if err != nil { - console.Fatal("IsEnabled error: %v", err) - os.Exit(1) + exit.WithError("IsEnabled failed", err) } if !ok { console.ErrStyle("conflict", `addon '%s' is currently not enabled. To enable this addon run: minikube addons enable %s`, addonName, addonName) - os.Exit(1) + os.Exit(exit.Unavailable) } namespace := "kube-system" @@ -91,15 +87,11 @@ minikube addons enable %s`, addonName, addonName) serviceList, err := service.GetServiceListByLabel(namespace, key, addonName) if err != nil { - console.Fatal("Error getting service with namespace: %s and labels %s:%s: %v", namespace, key, addonName, err) - os.Exit(1) + exit.Fail("Error getting service with namespace: %s and labels %s:%s: %v", namespace, key, addonName, err) } if len(serviceList.Items) == 0 { - console.Fatal(` -This addon does not have an endpoint defined for the 'addons open' command -You can add one by annotating a service with the label %s:%s -`, key, addonName) - os.Exit(1) + exit.WithCode(exit.Config, `This addon does not have an endpoint defined for the 'addons open' command. +You can add one by annotating a service with the label %s:%s`, key, addonName) } for i := range serviceList.Items { svc := serviceList.Items[i].ObjectMeta.Name diff --git a/cmd/minikube/cmd/config/profile.go b/cmd/minikube/cmd/config/profile.go index f74c85baf3..7d91e5f6c9 100644 --- a/cmd/minikube/cmd/config/profile.go +++ b/cmd/minikube/cmd/config/profile.go @@ -17,11 +17,10 @@ limitations under the License. package config import ( - "os" - "github.com/spf13/cobra" pkgConfig "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/console" + "k8s.io/minikube/pkg/minikube/exit" ) var ProfileCmd = &cobra.Command{ @@ -30,8 +29,7 @@ var ProfileCmd = &cobra.Command{ Long: "profile sets the current minikube profile. This is used to run and manage multiple minikube instance. You can return to the default minikube profile by running `minikube profile default`", Run: func(cmd *cobra.Command, args []string) { if len(args) != 1 { - console.ErrStyle("usage", "usage: minikube profile MINIKUBE_PROFILE_NAME") - os.Exit(1) + exit.Usage("usage: minikube profile MINIKUBE_PROFILE_NAME") } profile := args[0] @@ -40,8 +38,7 @@ var ProfileCmd = &cobra.Command{ } err := Set(pkgConfig.MachineProfile, profile) if err != nil { - console.Fatal("set failed: %v", err) - os.Exit(1) + exit.WithError("set failed", err) } else { console.Success("minikube profile was successfully set to %s", profile) } diff --git a/cmd/minikube/cmd/config/set.go b/cmd/minikube/cmd/config/set.go index 507eece7e5..aa0b20b8d7 100644 --- a/cmd/minikube/cmd/config/set.go +++ b/cmd/minikube/cmd/config/set.go @@ -17,11 +17,9 @@ limitations under the License. package config import ( - "os" - "github.com/spf13/cobra" pkgConfig "k8s.io/minikube/pkg/minikube/config" - "k8s.io/minikube/pkg/minikube/console" + "k8s.io/minikube/pkg/minikube/exit" ) var configSetCmd = &cobra.Command{ @@ -31,13 +29,11 @@ var configSetCmd = &cobra.Command{ These values can be overwritten by flags or environment variables at runtime.`, Run: func(cmd *cobra.Command, args []string) { if len(args) != 2 { - console.ErrStyle("usage", "usage: minikube config set PROPERTY_NAME PROPERTY_VALUE") - os.Exit(1) + exit.Usage("usage: minikube config set PROPERTY_NAME PROPERTY_VALUE") } err := Set(args[0], args[1]) if err != nil { - console.Fatal("Set failed: %v", err) - os.Exit(1) + exit.WithError("Set failed", err) } }, } diff --git a/cmd/minikube/cmd/config/unset.go b/cmd/minikube/cmd/config/unset.go index 3ef9ee8818..1ea0723405 100644 --- a/cmd/minikube/cmd/config/unset.go +++ b/cmd/minikube/cmd/config/unset.go @@ -17,11 +17,9 @@ limitations under the License. package config import ( - "os" - "github.com/spf13/cobra" pkgConfig "k8s.io/minikube/pkg/minikube/config" - "k8s.io/minikube/pkg/minikube/console" + "k8s.io/minikube/pkg/minikube/exit" ) var configUnsetCmd = &cobra.Command{ @@ -30,12 +28,11 @@ var configUnsetCmd = &cobra.Command{ Long: "unsets PROPERTY_NAME from the minikube config file. Can be overwritten by flags or environmental variables", Run: func(cmd *cobra.Command, args []string) { if len(args) != 1 { - console.ErrStyle("usage", "usage: minikube config unset PROPERTY_NAME") - os.Exit(1) + exit.Usage("usage: minikube config unset PROPERTY_NAME") } err := unset(args[0]) if err != nil { - console.Fatal("unset failed: %v", err) + exit.WithError("unset failed", err) } }, } diff --git a/cmd/minikube/cmd/config/util.go b/cmd/minikube/cmd/config/util.go index 40d1d94f28..e7201f8d84 100644 --- a/cmd/minikube/cmd/config/util.go +++ b/cmd/minikube/cmd/config/util.go @@ -18,7 +18,6 @@ package config import ( "fmt" - "os" "strconv" "strings" @@ -26,7 +25,6 @@ import ( "k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/config" - "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/storageclass" @@ -106,8 +104,7 @@ func EnableOrDisableAddon(name string, val string) error { //TODO(r2d4): config package should not reference API, pull this out api, err := machine.NewAPIClient() if err != nil { - console.Fatal("Error getting client: %v", err) - os.Exit(1) + return errors.Wrap(err, "machine client") } defer api.Close() cluster.EnsureMinikubeRunningOrExit(api, 0) diff --git a/cmd/minikube/cmd/dashboard.go b/cmd/minikube/cmd/dashboard.go index fd45f011f2..7f23f5b4a5 100644 --- a/cmd/minikube/cmd/dashboard.go +++ b/cmd/minikube/cmd/dashboard.go @@ -21,7 +21,6 @@ import ( "fmt" "io" "net/http" - "os" "os/exec" "regexp" "time" @@ -34,6 +33,7 @@ import ( "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/console" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/service" "k8s.io/minikube/pkg/util" @@ -61,8 +61,7 @@ var dashboardCmd = &cobra.Command{ }() if err != nil { - console.Fatal("Error getting client: %v", err) - os.Exit(1) + exit.WithError("Error getting client", err) } cluster.EnsureMinikubeRunningOrExit(api, 1) @@ -71,29 +70,26 @@ var dashboardCmd = &cobra.Command{ // Enable the dashboard add-on err = configcmd.Set("dashboard", "true") if err != nil { - console.Fatal("Unable to enable dashboard: %v", err) - os.Exit(1) + exit.WithError("Unable to enable dashboard", err) } ns := "kube-system" svc := "kubernetes-dashboard" console.ErrStyle("verifying", "Verifying dashboard health ...") if err = util.RetryAfter(180, func() error { return service.CheckService(ns, svc) }, 1*time.Second); err != nil { - console.Fatal("%s:%s is not running: %v", ns, svc, err) - os.Exit(1) + exit.WithCode(exit.Unavailable, "%s:%s is not running: %v", ns, svc, err) } console.ErrStyle("launch", "Launching proxy ...") p, hostPort, err := kubectlProxy() if err != nil { - glog.Fatalf("kubectl proxy: %v", err) + exit.WithError("kubectl proxy", err) } url := dashboardURL(hostPort, ns, svc) console.ErrStyle("verifying", "Verifying proxy health ...") if err = util.RetryAfter(60, func() error { return checkURL(url) }, 1*time.Second); err != nil { - console.Fatal("%s is not responding properly: %v", url, err) - os.Exit(1) + exit.WithCode(exit.Unavailable, "%s is not responding properly: %v", url, err) } if dashboardURLMode { diff --git a/cmd/minikube/cmd/delete.go b/cmd/minikube/cmd/delete.go index 03da06be14..6037abb256 100644 --- a/cmd/minikube/cmd/delete.go +++ b/cmd/minikube/cmd/delete.go @@ -29,6 +29,7 @@ import ( pkg_config "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" ) @@ -40,14 +41,12 @@ var deleteCmd = &cobra.Command{ associated files.`, Run: func(cmd *cobra.Command, args []string) { if len(args) > 0 { - console.ErrStyle("usage", "usage: minikube delete") - os.Exit(1) + exit.Usage("usage: minikube delete") } profile := viper.GetString(pkg_config.MachineProfile) api, err := machine.NewAPIClient() if err != nil { - console.Fatal("Error getting client: %v", err) - os.Exit(1) + exit.WithError("Error getting client", err) } defer api.Close() @@ -72,8 +71,7 @@ associated files.`, case mcnerror.ErrHostDoesNotExist: console.OutStyle("meh", "%q VM does not exist", profile) default: - console.Fatal("Failed to delete VM: %v", err) - os.Exit(1) + exit.WithError("Failed to delete VM", err) } } else { console.OutStyle("crushed", "VM deleted.") @@ -88,8 +86,7 @@ associated files.`, console.OutStyle("meh", "%q profile does not exist", profile) os.Exit(0) } - console.Fatal("Failed to remove profile: %v", err) - os.Exit(1) + exit.WithError("Failed to remove profile", err) } console.Success("Removed %q profile!", profile) }, diff --git a/cmd/minikube/cmd/env.go b/cmd/minikube/cmd/env.go index e0ef862def..6bb22cd888 100644 --- a/cmd/minikube/cmd/env.go +++ b/cmd/minikube/cmd/env.go @@ -28,14 +28,12 @@ import ( "github.com/docker/machine/libmachine" "github.com/docker/machine/libmachine/host" "github.com/docker/machine/libmachine/shell" - "github.com/golang/glog" "github.com/pkg/errors" "github.com/spf13/cobra" - cmdUtil "k8s.io/minikube/cmd/util" "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/config" - "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" ) @@ -311,23 +309,19 @@ var dockerEnvCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { api, err := machine.NewAPIClient() if err != nil { - console.Fatal("Error getting client: %v", err) - os.Exit(1) + exit.WithError("Error getting client", err) } defer api.Close() host, err := cluster.CheckIfHostExistsAndLoad(api, config.GetMachineName()) if err != nil { - console.Fatal("Error getting host: %v", err) - os.Exit(1) + exit.WithError("Error getting host", err) } if host.Driver.DriverName() == "none" { - console.Fatal(`'none' driver does not support 'minikube docker-env' command`) - os.Exit(1) + exit.Usage(`'none' driver does not support 'minikube docker-env' command`) } docker, err := GetDockerActive(host) if !docker { - console.OutLn(`# The docker service is currently not active`) - os.Exit(1) + exit.WithCode(exit.Unavailable, `# The docker service is currently not active`) } var shellCfg *ShellConfig @@ -335,14 +329,12 @@ var dockerEnvCmd = &cobra.Command{ if unset { shellCfg, err = shellCfgUnset() if err != nil { - glog.Errorln("Error setting machine env variable(s):", err) - cmdUtil.MaybeReportErrorAndExit(err) + exit.WithError("Error unsetting shell variables", err) } } else { shellCfg, err = shellCfgSet(api) if err != nil { - glog.Errorln("Error setting machine env variable(s):", err) - cmdUtil.MaybeReportErrorAndExit(err) + exit.WithError("Error setting shell variables", err) } } diff --git a/cmd/minikube/cmd/ip.go b/cmd/minikube/cmd/ip.go index 5495800648..a066959a41 100644 --- a/cmd/minikube/cmd/ip.go +++ b/cmd/minikube/cmd/ip.go @@ -17,11 +17,12 @@ limitations under the License. package cmd import ( - "os" - + "github.com/docker/machine/libmachine/mcnerror" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/console" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" ) @@ -33,19 +34,22 @@ var ipCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { api, err := machine.NewAPIClient() if err != nil { - console.Fatal("Error getting client: %v", err) - os.Exit(1) + exit.WithError("Error getting client", err) } defer api.Close() + host, err := api.Load(config.GetMachineName()) if err != nil { - console.Fatal("Error getting host: %v", err) - os.Exit(1) + switch err := errors.Cause(err).(type) { + case mcnerror.ErrHostDoesNotExist: + exit.WithCode(exit.NoInput, "%q host does not exist, unable to show an IP", config.GetMachineName()) + default: + exit.WithError("Error getting host", err) + } } ip, err := host.Driver.GetIP() if err != nil { - console.Fatal("Error getting IP: %v", err) - os.Exit(1) + exit.WithError("Error getting IP", err) } console.OutLn(ip) }, diff --git a/cmd/minikube/cmd/logs.go b/cmd/minikube/cmd/logs.go index 4a632d772a..5340cd0c50 100644 --- a/cmd/minikube/cmd/logs.go +++ b/cmd/minikube/cmd/logs.go @@ -19,12 +19,10 @@ package cmd import ( "os" - "github.com/golang/glog" "github.com/spf13/cobra" "github.com/spf13/viper" cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config" - cmdUtil "k8s.io/minikube/cmd/util" - "k8s.io/minikube/pkg/minikube/console" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" ) @@ -40,19 +38,17 @@ var logsCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { api, err := machine.NewAPIClient() if err != nil { - console.Fatal("Error getting client: %v", err) - os.Exit(1) + exit.WithError("Error getting client", err) } defer api.Close() clusterBootstrapper, err := GetClusterBootstrapper(api, viper.GetString(cmdcfg.Bootstrapper)) if err != nil { - glog.Exitf("Error getting cluster bootstrapper: %v", err) + exit.WithError("Error getting cluster bootstrapper", err) } err = clusterBootstrapper.GetClusterLogsTo(follow, os.Stdout) if err != nil { - console.Fatal("Error getting machine logs:", err) - cmdUtil.MaybeReportErrorAndExit(err) + exit.WithError("Error getting machine logs", err) } }, } diff --git a/cmd/minikube/cmd/mount.go b/cmd/minikube/cmd/mount.go index ca33e151d1..ff56d0cace 100644 --- a/cmd/minikube/cmd/mount.go +++ b/cmd/minikube/cmd/mount.go @@ -29,6 +29,7 @@ import ( "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/third_party/go9p/ufs" ) @@ -48,37 +49,32 @@ var mountCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { if isKill { if err := cmdUtil.KillMountProcess(); err != nil { - console.Fatal("Error killing mount process: ", err) - os.Exit(1) + exit.WithError("Error killing mount process", err) } os.Exit(0) } if len(args) != 1 { - console.ErrStyle("usage", `Please specify the directory to be mounted: + exit.Usage(`Please specify the directory to be mounted: minikube mount HOST_MOUNT_DIRECTORY:VM_MOUNT_DIRECTORY(ex:"/host-home:/vm-home")`) - os.Exit(1) } mountString := args[0] idx := strings.LastIndex(mountString, ":") if idx == -1 { // no ":" was present - console.ErrStyle("usage", `Mount directory must be in the form: + exit.Usage(`Mount directory must be in the form: HOST_MOUNT_DIRECTORY:VM_MOUNT_DIRECTORY`) - os.Exit(1) } hostPath := mountString[:idx] vmPath := mountString[idx+1:] if _, err := os.Stat(hostPath); err != nil { if os.IsNotExist(err) { - console.Fatal("Cannot find directory %s for mount", hostPath) + exit.WithCode(exit.NoInput, "Cannot find directory %s for mount", hostPath) } else { - console.Fatal("Error accessing directory %s for mount", hostPath) + exit.WithError("stat failed", err) } - os.Exit(1) } if len(vmPath) == 0 || !strings.HasPrefix(vmPath, "/") { - console.ErrStyle("usage", "The :VM_MOUNT_DIRECTORY must be an absolute path") - os.Exit(1) + exit.Usage("The :VM_MOUNT_DIRECTORY must be an absolute path") } var debugVal int if glog.V(1) { @@ -86,39 +82,33 @@ var mountCmd = &cobra.Command{ } api, err := machine.NewAPIClient() if err != nil { - console.Fatal("Error getting client: %v", err) - os.Exit(1) + exit.WithError("Error getting client", err) } defer api.Close() host, err := api.Load(config.GetMachineName()) if err != nil { - console.Fatal("Error loading api: %v", err) - os.Exit(1) + exit.WithError("Error loading api", err) } if host.Driver.DriverName() == "none" { - console.Fatal(`'none' driver does not support 'minikube mount' command`) - os.Exit(0) + exit.Usage(`'none' driver does not support 'minikube mount' command`) } var ip net.IP if mountIP == "" { ip, err = cluster.GetVMHostIP(host) if err != nil { - glog.Errorln("Error getting the host IP address to use from within the VM: ", err) - os.Exit(1) + exit.WithError("Error getting the host IP address to use from within the VM", err) } } else { ip = net.ParseIP(mountIP) if ip == nil { - glog.Errorln("error parsing the input ip address for mount") - os.Exit(1) + exit.WithCode(exit.Data, "error parsing the input ip address for mount") } } console.OutStyle("mounting", "Mounting %s into %s on the minikube VM", hostPath, vmPath) console.OutStyle("notice", "This daemon process needs to stay alive for the mount to be accessible ...") port, err := cmdUtil.GetPort() if err != nil { - console.Fatal("Error finding port for mount: %v", err) - os.Exit(1) + exit.WithError("Error finding port for mount", err) } var wg sync.WaitGroup wg.Add(1) @@ -128,8 +118,7 @@ var mountCmd = &cobra.Command{ }() err = cluster.MountHost(api, ip, vmPath, port, mountVersion, uid, gid, msize) if err != nil { - console.Fatal(err.Error()) - os.Exit(1) + exit.WithError("failed to mount host", err) } wg.Wait() }, diff --git a/cmd/minikube/cmd/root.go b/cmd/minikube/cmd/root.go index 60accb97d4..9bc7791868 100644 --- a/cmd/minikube/cmd/root.go +++ b/cmd/minikube/cmd/root.go @@ -37,6 +37,7 @@ import ( "k8s.io/minikube/pkg/minikube/bootstrapper/kubeadm" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/notify" ) @@ -70,7 +71,7 @@ var RootCmd = &cobra.Command{ PersistentPreRun: func(cmd *cobra.Command, args []string) { for _, path := range dirs { if err := os.MkdirAll(path, 0777); err != nil { - glog.Exitf("Error creating minikube directory: %v", err) + exit.WithError("Error creating minikube directory", err) } } @@ -101,7 +102,8 @@ var RootCmd = &cobra.Command{ // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { if err := RootCmd.Execute(); err != nil { - os.Exit(1) + // Cobra already outputs the error, typically because the user provided an unknown command. + os.Exit(exit.BadUsage) } } diff --git a/cmd/minikube/cmd/service.go b/cmd/minikube/cmd/service.go index a7422b930a..47c763ec94 100644 --- a/cmd/minikube/cmd/service.go +++ b/cmd/minikube/cmd/service.go @@ -17,13 +17,12 @@ limitations under the License. package cmd import ( - "os" "text/template" "github.com/spf13/cobra" "k8s.io/minikube/pkg/minikube/cluster" - "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/service" ) @@ -48,8 +47,7 @@ var serviceCmd = &cobra.Command{ PersistentPreRun: func(cmd *cobra.Command, args []string) { t, err := template.New("serviceURL").Parse(serviceURLFormat) if err != nil { - console.Fatal("The value passed to --format is invalid: %v", err) - os.Exit(1) + exit.WithError("The value passed to --format is invalid", err) } serviceURLTemplate = t @@ -57,15 +55,13 @@ var serviceCmd = &cobra.Command{ }, Run: func(cmd *cobra.Command, args []string) { if len(args) == 0 || len(args) > 1 { - console.Fatal("No service name was specified.") - os.Exit(1) + exit.Usage("You must specify a service name") } svc := args[0] api, err := machine.NewAPIClient() if err != nil { - console.Fatal("Error getting client: %v", err) - os.Exit(1) + exit.WithError("Error getting client", err) } defer api.Close() @@ -73,8 +69,7 @@ var serviceCmd = &cobra.Command{ err = service.WaitAndMaybeOpenService(api, namespace, svc, serviceURLTemplate, serviceURLMode, https, wait, interval) if err != nil { - console.Fatal("Error opening service: %v", err) - os.Exit(1) + exit.WithError("Error opening service", err) } }, } diff --git a/cmd/minikube/cmd/service_list.go b/cmd/minikube/cmd/service_list.go index d47a5c1653..0fa33ed40c 100644 --- a/cmd/minikube/cmd/service_list.go +++ b/cmd/minikube/cmd/service_list.go @@ -24,6 +24,7 @@ import ( "github.com/spf13/cobra" "k8s.io/api/core/v1" "k8s.io/minikube/pkg/minikube/console" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/service" ) @@ -38,15 +39,14 @@ var serviceListCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { api, err := machine.NewAPIClient() if err != nil { - console.Fatal("Error getting client: %v", err) - os.Exit(1) + exit.WithError("Error getting client", err) } defer api.Close() serviceURLs, err := service.GetServiceURLs(api, serviceListNamespace, serviceURLTemplate) if err != nil { console.Fatal("Failed to get service URL: %v", err) console.ErrStyle("notice", "Check that minikube is running and that you have specified the correct namespace (-n flag) if required.") - os.Exit(1) + os.Exit(exit.Unavailable) } var data [][]string diff --git a/cmd/minikube/cmd/ssh.go b/cmd/minikube/cmd/ssh.go index d7e65b6521..b20811b84f 100644 --- a/cmd/minikube/cmd/ssh.go +++ b/cmd/minikube/cmd/ssh.go @@ -17,12 +17,10 @@ limitations under the License. package cmd import ( - "os" - "github.com/spf13/cobra" "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/config" - "k8s.io/minikube/pkg/minikube/console" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" ) @@ -34,23 +32,19 @@ var sshCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { api, err := machine.NewAPIClient() if err != nil { - console.Fatal("Error getting client: %v", err) - os.Exit(1) + exit.WithError("Error getting client", err) } defer api.Close() host, err := cluster.CheckIfHostExistsAndLoad(api, config.GetMachineName()) if err != nil { - console.Fatal("Error getting host: %v", err) - os.Exit(1) + exit.WithError("Error getting host", err) } if host.Driver.DriverName() == "none" { - console.Fatal(`'none' driver does not support 'minikube ssh' command`) - os.Exit(1) + exit.Usage("'none' driver does not support 'minikube ssh' command") } err = cluster.CreateSSHShell(api, args) if err != nil { - console.Fatal("Error creating SSH shell: %v", err) - os.Exit(1) + exit.WithError("Error creating SSH shell", err) } }, } diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index dba7186966..e20be29fc9 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -45,6 +45,7 @@ import ( "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/cruntime" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" pkgutil "k8s.io/minikube/pkg/util" "k8s.io/minikube/pkg/util/kubeconfig" @@ -157,12 +158,12 @@ func runStart(cmd *cobra.Command, args []string) { oldConfig, err := cfg.Load() if err != nil && !os.IsNotExist(err) { - fatalExit("Unable to load config: %v", err) + exit.WithCode(exit.Data, "Unable to load config: %v", err) } kVersion := validateKubernetesVersions(oldConfig) config, err := generateConfig(cmd, kVersion) if err != nil { - reportErrAndExit("Failed to generate config: %v", err) + exit.WithError("Failed to generate config", err) } var cacheGroup errgroup.Group @@ -171,12 +172,12 @@ func runStart(cmd *cobra.Command, args []string) { // Abstraction leakage alert: startHost requires the config to be saved, to satistfy pkg/provision/buildroot. // Hence, saveConfig must be called before startHost, and again afterwards when we know the IP. if err := saveConfig(config); err != nil { - reportErrAndExit("Failed to save config", err) + exit.WithError("Failed to save config", err) } m, err := machine.NewAPIClient() if err != nil { - reportErrAndExit("Failed to get machine client: %v", err) + exit.WithError("Failed to get machine client", err) } host, preexisting := startHost(m, config.MachineConfig) @@ -184,7 +185,7 @@ func runStart(cmd *cobra.Command, args []string) { // Save IP to configuration file for subsequent use config.KubernetesConfig.NodeIP = ip if err := saveConfig(config); err != nil { - reportErrAndExit("Failed to save config", err) + exit.WithError("Failed to save config", err) } configureRuntimes(host) @@ -212,11 +213,11 @@ func runStart(cmd *cobra.Command, args []string) { func validateConfig() { diskSizeMB := pkgutil.CalculateDiskSizeInMB(viper.GetString(humanReadableDiskSize)) if diskSizeMB < constants.MinimumDiskSizeMB { - fatalExit("Requested disk size (%dMB) is less than minimum of %dMB", diskSizeMB, constants.MinimumDiskSizeMB) + exit.WithCode(exit.Config, "Requested disk size (%dMB) is less than minimum of %dMB", diskSizeMB, constants.MinimumDiskSizeMB) } if viper.GetBool(gpu) && viper.GetString(vmDriver) != "kvm2" { - fatalExit("Sorry, the --gpu feature is currently only supported with --vm-driver=kvm2") + exit.Usage("Sorry, the --gpu feature is currently only supported with --vm-driver=kvm2") } } @@ -316,7 +317,7 @@ This can also be done automatically by setting the env var CHANGE_MINIKUBE_NONE_ } if err := pkgutil.MaybeChownDirRecursiveToMinikubeUser(constants.GetMinipath()); err != nil { - fatalExit("Failed to chown %s: %v", constants.GetMinipath(), err) + exit.WithCode(exit.Permissions, "Failed to chown %s: %v", constants.GetMinipath(), err) } } @@ -324,7 +325,7 @@ This can also be done automatically by setting the env var CHANGE_MINIKUBE_NONE_ func startHost(api libmachine.API, mc cfg.MachineConfig) (*host.Host, bool) { exists, err := api.Exists(cfg.GetMachineName()) if err != nil { - reportErrAndExit("Failed to check if machine exists", err) + exit.WithError("Failed to check if machine exists", err) } if mc.VMDriver == constants.DriverNone { console.OutStyle("starting-none", "Configuring local host environment ...") @@ -346,7 +347,7 @@ func startHost(api libmachine.API, mc cfg.MachineConfig) (*host.Host, bool) { return err } if err = pkgutil.RetryAfter(3, start, 2*time.Second); err != nil { - reportErrAndExit("Unable to start VM", err) + exit.WithError("Unable to start VM", err) } return host, exists } @@ -355,7 +356,7 @@ func startHost(api libmachine.API, mc cfg.MachineConfig) (*host.Host, bool) { func validateNetwork(h *host.Host) string { ip, err := h.Driver.GetIP() if err != nil { - reportErrAndExit("Unable to get VM IP address", err) + exit.WithError("Unable to get VM IP address", err) } console.OutStyle("connectivity", "%q IP address is %s", cfg.GetMachineName(), ip) @@ -382,7 +383,7 @@ func validateKubernetesVersions(old *cfg.Config) string { } nvs, err := semver.Make(strings.TrimPrefix(nv, version.VersionPrefix)) if err != nil { - fatalExit("Unable to parse %q: %v", nv, err) + exit.WithCode(exit.Data, "Unable to parse %q: %v", nv, err) } if old == nil || old.KubernetesConfig.KubernetesVersion == "" { @@ -409,7 +410,7 @@ func validateKubernetesVersions(old *cfg.Config) string { func prepareHostEnvironment(api libmachine.API, kc cfg.KubernetesConfig) bootstrapper.Bootstrapper { bs, err := GetClusterBootstrapper(api, viper.GetString(cmdcfg.Bootstrapper)) if err != nil { - reportErrAndExit("Failed to get bootstrapper", err) + exit.WithError("Failed to get bootstrapper", err) } console.OutStyle("copying", "Preparing Kubernetes environment ...") for _, eo := range extraOptions { @@ -417,10 +418,10 @@ func prepareHostEnvironment(api libmachine.API, kc cfg.KubernetesConfig) bootstr } // Loads cached images, generates config files, download binaries if err := bs.UpdateCluster(kc); err != nil { - reportErrAndExit("Failed to update cluster", err) + exit.WithError("Failed to update cluster", err) } if err := bs.SetupCerts(kc); err != nil { - reportErrAndExit("Failed to setup certs", err) + exit.WithError("Failed to setup certs", err) } return bs } @@ -429,7 +430,7 @@ func prepareHostEnvironment(api libmachine.API, kc cfg.KubernetesConfig) bootstr func updateKubeConfig(h *host.Host, c *cfg.Config) *kubeconfig.KubeConfigSetup { addr, err := h.Driver.GetURL() if err != nil { - reportErrAndExit("Failed to get driver URL", err) + exit.WithError("Failed to get driver URL", err) } addr = strings.Replace(addr, "tcp://", "https://", -1) addr = strings.Replace(addr, ":2376", ":"+strconv.Itoa(c.KubernetesConfig.NodePort), -1) @@ -445,7 +446,7 @@ func updateKubeConfig(h *host.Host, c *cfg.Config) *kubeconfig.KubeConfigSetup { } kcs.SetKubeConfigFile(cmdutil.GetKubeConfigPath()) if err := kubeconfig.SetupKubeConfig(kcs); err != nil { - reportErrAndExit("Failed to setup kubeconfig", err) + exit.WithError("Failed to setup kubeconfig", err) } return kcs } @@ -454,14 +455,13 @@ func updateKubeConfig(h *host.Host, c *cfg.Config) *kubeconfig.KubeConfigSetup { func configureRuntimes(h *host.Host) { runner, err := machine.CommandRunner(h) if err != nil { - reportErrAndExit("Failed to get command runner", err) + exit.WithError("Failed to get command runner", err) } config := cruntime.Config{Type: viper.GetString(containerRuntime), Runner: runner} cr, err := cruntime.New(config) if err != nil { - reportErrAndExit(fmt.Sprintf("Failed runtime for %+v", config), err) - cmdutil.MaybeReportErrorAndExit(err) + exit.WithError(fmt.Sprintf("Failed runtime for %+v", config), err) } console.OutStyle(cr.Name(), "Configuring %s as your container runtime ...", cr.Name()) for _, v := range dockerOpt { @@ -473,7 +473,7 @@ func configureRuntimes(h *host.Host) { err = cr.Enable() if err != nil { - cmdutil.MaybeReportErrorAndExit(err) + exit.WithError("Failed to enable container runtime", err) } } @@ -493,7 +493,7 @@ func waitCacheImages(g *errgroup.Group) { func bootstrapCluster(bs bootstrapper.Bootstrapper, kc cfg.KubernetesConfig, preexisting bool) { console.OutStyle("pulling", "Pulling images used by Kubernetes %s ...", kc.KubernetesVersion) if err := bs.PullImages(kc); err != nil { - fmt.Printf("Unable to pull images, which may be OK: %v", err) + console.OutStyle("failure", "Unable to pull images, which may be OK: %v", err) } // hum. bootstrapper.Bootstrapper should probably have a Name function. bsName := viper.GetString(cmdcfg.Bootstrapper) @@ -501,14 +501,14 @@ func bootstrapCluster(bs bootstrapper.Bootstrapper, kc cfg.KubernetesConfig, pre if preexisting { console.OutStyle("restarting", "Relaunching Kubernetes %s using %s ... ", kc.KubernetesVersion, bsName) if err := bs.RestartCluster(kc); err != nil { - reportErrAndExit("Error restarting cluster", err) + exit.WithError("Error restarting cluster", err) } return } console.OutStyle("launch", "Launching Kubernetes %s using %s ... ", kc.KubernetesVersion, bsName) if err := bs.StartCluster(kc); err != nil { - reportErrAndExit("Error starting cluster", err) + exit.WithError("Error starting cluster", err) } } @@ -525,7 +525,7 @@ func validateCluster(bs bootstrapper.Bootstrapper, ip string) { } err := pkgutil.RetryAfter(20, kStat, 3*time.Second) if err != nil { - reportErrAndExit("kubelet checks failed", err) + exit.WithError("kubelet checks failed", err) } aStat := func() (err error) { st, err := bs.GetApiServerStatus(net.ParseIP(ip)) @@ -538,7 +538,7 @@ func validateCluster(bs bootstrapper.Bootstrapper, ip string) { err = pkgutil.RetryAfter(30, aStat, 10*time.Second) if err != nil { - reportErrAndExit("apiserver checks failed", err) + exit.WithError("apiserver checks failed", err) } console.OutLn("") } @@ -562,12 +562,10 @@ func configureMounts() { mountCmd.Stderr = os.Stderr } if err := mountCmd.Start(); err != nil { - glog.Errorf("Error running command minikube mount %v", err) - cmdutil.MaybeReportErrorAndExit(err) + exit.WithError("Error starting mount", err) } if err := ioutil.WriteFile(filepath.Join(constants.GetMinipath(), constants.MountProcessFileName), []byte(strconv.Itoa(mountCmd.Process.Pid)), 0644); err != nil { - glog.Errorf("Error writing mount process pid to file: %v", err) - cmdutil.MaybeReportErrorAndExit(err) + exit.WithError("Error writing mount pid", err) } } @@ -614,18 +612,3 @@ func saveConfig(clusterConfig cfg.Config) error { } return nil } - -// fatalExit is a shortcut for outputting a failure message and exiting. -func fatalExit(format string, a ...interface{}) { - // use Warning because Error will display a duplicate message - glog.Warningf(format, a...) - console.Fatal(format, a...) - os.Exit(1) -} - -// reportFatalExit is a shortcut for outputting an error, reporting it, and exiting. -func reportErrAndExit(msg string, err error) { - console.Fatal(msg+": %v", err) - cmdutil.MaybeReportErrorAndExit(err) - os.Exit(1) -} diff --git a/cmd/minikube/cmd/status.go b/cmd/minikube/cmd/status.go index ccc7fa63bc..e6ea1af9d3 100644 --- a/cmd/minikube/cmd/status.go +++ b/cmd/minikube/cmd/status.go @@ -25,11 +25,11 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config" - cmdUtil "k8s.io/minikube/cmd/util" + "k8s.io/minikube/cmd/util" "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/config" - "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/util/kubeconfig" ) @@ -43,8 +43,6 @@ type Status struct { Kubeconfig string } -const internalErrorCode = -1 - const ( minikubeNotRunningStatusFlag = 1 << 0 clusterNotRunningStatusFlag = 1 << 1 @@ -62,15 +60,13 @@ var statusCmd = &cobra.Command{ var returnCode = 0 api, err := machine.NewAPIClient() if err != nil { - console.Fatal("Error getting client: %v", err) - os.Exit(internalErrorCode) + exit.WithCode(exit.Unavailable, "Error getting client: %v", err) } defer api.Close() hostSt, err := cluster.GetHostStatus(api) if err != nil { - glog.Errorln("Error getting machine status:", err) - cmdUtil.MaybeReportErrorAndExitWithCode(err, internalErrorCode) + exit.WithError("Error getting host status", err) } kubeletSt := state.None.String() @@ -80,13 +76,12 @@ var statusCmd = &cobra.Command{ if hostSt == state.Running.String() { clusterBootstrapper, err := GetClusterBootstrapper(api, viper.GetString(cmdcfg.Bootstrapper)) if err != nil { - glog.Errorf("Error getting cluster bootstrapper: %v", err) - cmdUtil.MaybeReportErrorAndExitWithCode(err, internalErrorCode) + exit.WithError("Error getting bootstrapper", err) } kubeletSt, err = clusterBootstrapper.GetKubeletStatus() if err != nil { - glog.Errorln("Error kubelet status:", err) - cmdUtil.MaybeReportErrorAndExitWithCode(err, internalErrorCode) + glog.Warningf("kubelet err: %v", err) + returnCode |= clusterNotRunningStatusFlag } else if kubeletSt != state.Running.String() { returnCode |= clusterNotRunningStatusFlag } @@ -94,21 +89,18 @@ var statusCmd = &cobra.Command{ ip, err := cluster.GetHostDriverIP(api, config.GetMachineName()) if err != nil { glog.Errorln("Error host driver ip status:", err) - cmdUtil.MaybeReportErrorAndExitWithCode(err, internalErrorCode) } apiserverSt, err = clusterBootstrapper.GetApiServerStatus(ip) if err != nil { glog.Errorln("Error apiserver status:", err) - cmdUtil.MaybeReportErrorAndExitWithCode(err, internalErrorCode) } else if apiserverSt != state.Running.String() { returnCode |= clusterNotRunningStatusFlag } - ks, err := kubeconfig.GetKubeConfigStatus(ip, cmdUtil.GetKubeConfigPath(), config.GetMachineName()) + ks, err := kubeconfig.GetKubeConfigStatus(ip, util.GetKubeConfigPath(), config.GetMachineName()) if err != nil { glog.Errorln("Error kubeconfig status:", err) - cmdUtil.MaybeReportErrorAndExitWithCode(err, internalErrorCode) } if ks { kubeconfigSt = "Correctly Configured: pointing to minikube-vm at " + ip.String() @@ -129,13 +121,11 @@ var statusCmd = &cobra.Command{ } tmpl, err := template.New("status").Parse(statusFormat) if err != nil { - glog.Errorln("Error creating status template:", err) - os.Exit(internalErrorCode) + exit.WithError("Error creating status template", err) } err = tmpl.Execute(os.Stdout, status) if err != nil { - glog.Errorln("Error executing status template:", err) - os.Exit(internalErrorCode) + exit.WithError("Error executing status template", err) } os.Exit(returnCode) diff --git a/cmd/minikube/cmd/stop.go b/cmd/minikube/cmd/stop.go index b4eeadebfe..2b51d73f82 100644 --- a/cmd/minikube/cmd/stop.go +++ b/cmd/minikube/cmd/stop.go @@ -17,7 +17,6 @@ limitations under the License. package cmd import ( - "os" "time" "github.com/docker/machine/libmachine/mcnerror" @@ -28,6 +27,7 @@ import ( "k8s.io/minikube/pkg/minikube/cluster" pkg_config "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/console" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" pkgutil "k8s.io/minikube/pkg/util" ) @@ -44,8 +44,7 @@ itself, leaving all files intact. The cluster can be started again with the "sta api, err := machine.NewAPIClient() if err != nil { - console.Fatal("Error getting client: %v", err) - os.Exit(1) + exit.WithError("Error getting client", err) } defer api.Close() @@ -63,15 +62,14 @@ itself, leaving all files intact. The cluster can be started again with the "sta } } if err := pkgutil.RetryAfter(5, stop, 1*time.Second); err != nil { - console.Fatal("Unable to stop VM: %v", err) - cmdUtil.MaybeReportErrorAndExit(err) + exit.WithError("Unable to stop VM", err) } if !nonexistent { console.OutStyle("stopped", "%q stopped.", profile) } if err := cmdUtil.KillMountProcess(); err != nil { - console.Fatal("Unable to kill mount process: %v", err) + exit.WithError("Unable to kill mount process", err) } }, } diff --git a/cmd/minikube/cmd/tunnel.go b/cmd/minikube/cmd/tunnel.go index daa6cf7c9e..10264d25a7 100644 --- a/cmd/minikube/cmd/tunnel.go +++ b/cmd/minikube/cmd/tunnel.go @@ -20,14 +20,15 @@ import ( "context" "os" "os/signal" + "time" "github.com/golang/glog" "github.com/spf13/cobra" "k8s.io/minikube/pkg/minikube/config" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/service" "k8s.io/minikube/pkg/minikube/tunnel" - "time" ) var cleanup bool @@ -54,7 +55,7 @@ var tunnelCmd = &cobra.Command{ glog.Infof("Creating docker machine client...") api, err := machine.NewAPIClient() if err != nil { - glog.Fatalf("error creating dockermachine client: %s", err) + exit.WithError("error creating machine client", err) } glog.Infof("Creating k8s client...") @@ -64,7 +65,7 @@ var tunnelCmd = &cobra.Command{ //doesn't hang on the API server call during startup and shutdown time or if there is a temporary error. clientset, err := service.K8s.GetClientset(1 * time.Second) if err != nil { - glog.Fatalf("error creating K8S clientset: %s", err) + exit.WithError("error creating clientset", err) } ctrlC := make(chan os.Signal, 1) @@ -77,7 +78,7 @@ var tunnelCmd = &cobra.Command{ done, err := manager.StartTunnel(ctx, config.GetMachineName(), api, config.DefaultLoader, clientset.CoreV1()) if err != nil { - glog.Fatalf("error starting tunnel: %s", err) + exit.WithError("error starting tunnel", err) } <-done }, diff --git a/cmd/minikube/cmd/update-check.go b/cmd/minikube/cmd/update-check.go index dfa3040fb2..fe61530768 100644 --- a/cmd/minikube/cmd/update-check.go +++ b/cmd/minikube/cmd/update-check.go @@ -17,11 +17,10 @@ limitations under the License. package cmd import ( - "os" - "github.com/spf13/cobra" "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/notify" "k8s.io/minikube/pkg/version" ) @@ -38,13 +37,11 @@ var updateCheckCmd = &cobra.Command{ url := constants.GithubMinikubeReleasesURL r, err := notify.GetAllVersionsFromURL(url) if err != nil { - console.Fatal("Unable to fetch latest version info: %v", err) - os.Exit(1) + exit.WithError("Unable to fetch latest version info", err) } if len(r) < 1 { - console.Fatal("Update server returned an empty list") - os.Exit(2) + exit.WithCode(exit.Data, "Update server returned an empty list") } console.OutLn("CurrentVersion: %s", version.GetVersion()) diff --git a/cmd/minikube/cmd/update-context.go b/cmd/minikube/cmd/update-context.go index cd65c85ad1..b9e95d5a4d 100644 --- a/cmd/minikube/cmd/update-context.go +++ b/cmd/minikube/cmd/update-context.go @@ -17,15 +17,12 @@ limitations under the License. package cmd import ( - "os" - - "github.com/golang/glog" "github.com/spf13/cobra" - cmdUtil "k8s.io/minikube/cmd/util" "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" kcfg "k8s.io/minikube/pkg/util/kubeconfig" ) @@ -39,20 +36,17 @@ var updateContextCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { api, err := machine.NewAPIClient() if err != nil { - console.Fatal("Error getting client: %v", err) - os.Exit(1) + exit.WithError("Error getting client", err) } defer api.Close() machineName := config.GetMachineName() ip, err := cluster.GetHostDriverIP(api, machineName) if err != nil { - glog.Errorln("Error host driver ip status:", err) - cmdUtil.MaybeReportErrorAndExit(err) + exit.WithError("Error host driver ip status", err) } updated, err := kcfg.UpdateKubeconfigIP(ip, constants.KubeconfigPath, machineName) if err != nil { - glog.Errorln("Error kubeconfig status:", err) - cmdUtil.MaybeReportErrorAndExit(err) + exit.WithError("update config", err) } if updated { console.OutStyle("celebrate", "IP has been updated to point at %s", ip) diff --git a/cmd/util/util.go b/cmd/util/util.go index 007a0bd520..0f1afb5f41 100644 --- a/cmd/util/util.go +++ b/cmd/util/util.go @@ -14,34 +14,24 @@ See the License for the specific language governing permissions and limitations under the License. */ +// package util is a hodge-podge of utility functions that should be moved elsewhere. package util import ( - "bufio" - "bytes" - "encoding/json" "fmt" "io" "io/ioutil" "net" - "net/http" "os" "os/exec" "path/filepath" "runtime" "strconv" - "strings" - "time" - "github.com/golang/glog" "github.com/pkg/errors" "github.com/spf13/viper" - "golang.org/x/crypto/ssh/terminal" - minikubeConfig "k8s.io/minikube/cmd/minikube/cmd/config" "k8s.io/minikube/pkg/minikube/config" - "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" - "k8s.io/minikube/pkg/version" ) type ServiceContext struct { @@ -49,11 +39,6 @@ type ServiceContext struct { Version string `json:"version"` } -type Message struct { - Message string `json:"message"` - ServiceContext `json:"serviceContext"` -} - type LookPath func(filename string) (string, error) var lookPath LookPath @@ -62,145 +47,6 @@ func init() { lookPath = exec.LookPath } -func ReportError(err error, url string) error { - errMsg, err := FormatError(err) - if err != nil { - return errors.Wrap(err, "Error formatting error message") - } - jsonErrorMsg, err := MarshallError(errMsg, "default", version.GetVersion()) - if err != nil { - return errors.Wrap(err, "Error marshalling error message to JSON") - } - err = UploadError(jsonErrorMsg, url) - if err != nil { - return errors.Wrap(err, "Error uploading error message") - } - return nil -} - -func FormatError(err error) (string, error) { - if err == nil { - return "", errors.New("Error: ReportError was called with nil error value") - } - - type stackTracer interface { - StackTrace() errors.StackTrace - } - - errOutput := []string{} - errOutput = append(errOutput, err.Error()) - - if err, ok := err.(stackTracer); ok { - for _, f := range err.StackTrace() { - errOutput = append(errOutput, fmt.Sprintf("\tat %n(%v)", f, f)) - } - } else { - return "", errors.New("Error msg with no stack trace cannot be reported") - } - return strings.Join(errOutput, "\n"), nil -} - -func MarshallError(errMsg, service, version string) ([]byte, error) { - m := Message{errMsg, ServiceContext{service, version}} - b, err := json.Marshal(m) - if err != nil { - return nil, errors.Wrap(err, "") - } - return b, nil -} - -func UploadError(b []byte, url string) error { - req, err := http.NewRequest("POST", url, bytes.NewBuffer(b)) - if err != nil { - return errors.Wrap(err, "") - } - req.Header.Set("Content-Type", "application/json") - - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - return errors.Wrap(err, "") - } else if resp.StatusCode != 200 { - return errors.Errorf("Error sending error report to %s, got response code %d", url, resp.StatusCode) - } - return nil -} - -func MaybeReportErrorAndExit(errToReport error) { - MaybeReportErrorAndExitWithCode(errToReport, 1) -} - -// MaybeReportErrorAndExitWithCode prompts the user if they would like to report a stack trace, and exits. -func MaybeReportErrorAndExitWithCode(errToReport error, returnCode int) { - // TODO(#3623,3178): Replace with maybeReportErrorAndExitWithCode once StackDriver integration is improved. - glog.Infof("Error reporting is disabled in this release of minikube") - os.Exit(returnCode) -} - -// maybeReportErrorAndExitWithCode is deadcode -func maybeReportErrorAndExitWithCode(errToReport error, returnCode int) { - var err error - - if viper.GetBool(config.WantReportError) { - err = ReportError(errToReport, constants.ReportingURL) - } else if viper.GetBool(config.WantReportErrorPrompt) { - console.Err( - `================================================================================ -An error has occurred. Would you like to opt in to sending anonymized crash -information to minikube to help prevent future errors? - -To disable this prompt, run: 'minikube config set WantReportErrorPrompt false' -================================================================================`) - if PromptUserForAccept(os.Stdin) { - err = minikubeConfig.Set(config.WantReportError, "true") - if err == nil { - err = ReportError(errToReport, constants.ReportingURL) - } - } else { - console.ErrStyle("meh", "Bummer, perhaps next time!") - } - } - - // This happens when the error was created without errors.Wrap(), and thus has no trace data. - if err != nil { - glog.Infof("report error failed: %v", err) - } - os.Exit(returnCode) -} - -func getInput(input chan string, r io.Reader) { - reader := bufio.NewReader(r) - console.OutLn("Please enter your response [Y/n]: ") - response, err := reader.ReadString('\n') - if err != nil { - glog.Errorf(err.Error()) - } - input <- response -} - -func PromptUserForAccept(r io.Reader) bool { - if !terminal.IsTerminal(int(os.Stdout.Fd())) { - return false - } - input := make(chan string, 1) - go getInput(input, r) - select { - case response := <-input: - response = strings.ToLower(strings.TrimSpace(response)) - if response == "y" || response == "yes" || response == "" { - return true - } else if response == "n" || response == "no" { - return false - } else { - console.Warning("Invalid response, error reporting remains disabled. Must be in form [Y/n]") - return false - } - case <-time.After(30 * time.Second): - console.Warning("Prompt timed out.") - return false - } -} - func MaybePrintKubectlDownloadMsg(goos string, out io.Writer) { if !viper.GetBool(config.WantKubectlDownloadMsg) { return diff --git a/cmd/util/util_test.go b/cmd/util/util_test.go index ca57397966..14fe92bc38 100644 --- a/cmd/util/util_test.go +++ b/cmd/util/util_test.go @@ -19,18 +19,16 @@ package util import ( "bytes" "fmt" - "k8s.io/client-go/tools/clientcmd" "net/http" "net/http/httptest" "os" "strings" "testing" - "k8s.io/minikube/pkg/minikube/config" - "k8s.io/minikube/pkg/version" - "github.com/pkg/errors" "github.com/spf13/viper" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/minikube/pkg/minikube/config" ) func startTestHTTPServer(returnError bool, response string) *httptest.Server { @@ -43,65 +41,6 @@ func startTestHTTPServer(returnError bool, response string) *httptest.Server { })) } -func TestFormatError(t *testing.T) { - var testErr error - if _, err := FormatError(testErr); err == nil { - t.Fatalf("FormatError should have errored with a nil error input") - } - testErr = fmt.Errorf("Not a valid error to format as there is no stacktrace") - - if out, err := FormatError(testErr); err == nil { - t.Fatalf("FormatError should have errored with a non pkg/errors error (no stacktrace info): %s", out) - } - - testErr = errors.New("TestFormatError 1") - errors.Wrap(testErr, "TestFormatError 2") - errors.Wrap(testErr, "TestFormatError 3") - - _, err := FormatError(testErr) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } -} - -func TestMarshallError(t *testing.T) { - testErr := errors.New("TestMarshallError 1") - errors.Wrap(testErr, "TestMarshallError 2") - errors.Wrap(testErr, "TestMarshallError 3") - - errMsg, _ := FormatError(testErr) - if _, err := MarshallError(errMsg, "default", version.GetVersion()); err != nil { - t.Fatalf("Unexpected error: %v", err) - } -} - -func TestUploadError(t *testing.T) { - testErr := errors.New("TestUploadError 1") - errors.Wrap(testErr, "TestUploadError 2") - errors.Wrap(testErr, "TestUploadError 3") - errMsg, _ := FormatError(testErr) - jsonErrMsg, _ := MarshallError(errMsg, "default", version.GetVersion()) - - server := startTestHTTPServer(false, "http test") - if err := UploadError(jsonErrMsg, server.URL); err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - server = startTestHTTPServer(true, "failed to write report") - if err := UploadError(jsonErrMsg, server.URL); err == nil { - t.Fatalf("UploadError should have errored from a 400 response") - } -} - -func TestReportError(t *testing.T) { - testErr := errors.New("TestError 1") - - server := startTestHTTPServer(false, "http test") - if err := ReportError(testErr, server.URL); err != nil { - t.Fatalf("ReportError") - } -} - func revertLookPath(l LookPath) { lookPath = l } diff --git a/pkg/drivers/none/none.go b/pkg/drivers/none/none.go index 4298a96b63..1a75954dd5 100644 --- a/pkg/drivers/none/none.go +++ b/pkg/drivers/none/none.go @@ -25,9 +25,7 @@ import ( "github.com/golang/glog" "github.com/pkg/errors" "k8s.io/apimachinery/pkg/util/net" - - pkgdrivers "k8s.io/minikube/pkg/drivers" - // TODO(tstromberg): Extract CommandRunner into its own package + pkgdrivers "k8s.io/minikube/pkg/drivers" // TODO(tstromberg): Extract CommandRunner into its own package "k8s.io/minikube/pkg/minikube/bootstrapper" "k8s.io/minikube/pkg/minikube/cruntime" ) diff --git a/pkg/minikube/cluster/cluster.go b/pkg/minikube/cluster/cluster.go index 23d7a90c1d..a8941ac1f1 100644 --- a/pkg/minikube/cluster/cluster.go +++ b/pkg/minikube/cluster/cluster.go @@ -23,7 +23,6 @@ import ( "fmt" "html/template" "net" - "os" "os/exec" "regexp" "time" @@ -41,6 +40,7 @@ import ( cfg "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/registry" "k8s.io/minikube/pkg/util" pkgutil "k8s.io/minikube/pkg/util" @@ -243,9 +243,9 @@ func createHost(api libmachine.API, config cfg.MachineConfig) (*host.Host, error def, err := registry.Driver(config.VMDriver) if err != nil { if err == registry.ErrDriverNotFound { - glog.Exitf("Unsupported driver: %s\n", config.VMDriver) + exit.Usage("unsupported driver: %s", config.VMDriver) } else { - glog.Exit(err.Error()) + exit.WithError("error getting driver", err) } } @@ -422,12 +422,10 @@ func CreateSSHShell(api libmachine.API, args []string) error { func EnsureMinikubeRunningOrExit(api libmachine.API, exitStatus int) { s, err := GetHostStatus(api) if err != nil { - console.Fatal("Error getting machine status:", err) - os.Exit(1) + exit.WithError("Error getting machine status", err) } if s != state.Running.String() { - console.ErrStyle("conflict", "minikube is not running, so the service cannot be accessed") - os.Exit(exitStatus) + exit.WithCode(exit.Unavailable, "minikube is not running, so the service cannot be accessed") } } diff --git a/pkg/minikube/console/style.go b/pkg/minikube/console/style.go index 1380769995..895ea31bb2 100644 --- a/pkg/minikube/console/style.go +++ b/pkg/minikube/console/style.go @@ -47,8 +47,10 @@ var styles = map[string]style{ "waiting": {Prefix: "⌛ "}, "usage": {Prefix: "💡 "}, "launch": {Prefix: "🚀 "}, + "sad": {Prefix: "😿 "}, "thumbs-up": {Prefix: "👍 "}, "option": {Prefix: " ▪ "}, // Indented bullet + "url": {Prefix: "👉 "}, "crushed": {Prefix: "💔 "}, // Specialized purpose styles diff --git a/pkg/minikube/machine/client.go b/pkg/minikube/machine/client.go index 140c0327bb..612918d775 100644 --- a/pkg/minikube/machine/client.go +++ b/pkg/minikube/machine/client.go @@ -39,10 +39,10 @@ import ( "github.com/docker/machine/libmachine/state" "github.com/docker/machine/libmachine/swarm" "github.com/docker/machine/libmachine/version" - "github.com/golang/glog" "github.com/pkg/errors" "k8s.io/minikube/pkg/minikube/bootstrapper" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/registry" "k8s.io/minikube/pkg/minikube/sshutil" "k8s.io/minikube/pkg/provision" @@ -259,9 +259,10 @@ func (cg *CertGenerator) ValidateCertificate(addr string, authOptions *auth.Opti func registerDriver(driverName string) { def, err := registry.Driver(driverName) - if err != nil { - glog.Exitf("Unsupported driver: %s\n", driverName) + if err == registry.ErrDriverNotFound { + exit.Usage("unsupported driver: %s", driverName) + } else { + exit.WithError("error getting driver", err) } - plugin.RegisterDriver(def.DriverCreator()) }