diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index 56326fa41f72..7bbe224ec64a 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -561,9 +561,15 @@ func selectDriver(existing *config.ClusterConfig) registry.DriverState { return ds } - pick, alts := driver.Suggest(driver.Choices(viper.GetBool("vm"))) + choices := driver.Choices(viper.GetBool("vm")) + pick, alts, rejects := driver.Suggest(choices) if pick.Name == "" { - exit.WithCodeT(exit.Config, "Unable to determine a default driver to use. Try specifying --driver, or see https://minikube.sigs.k8s.io/docs/start/") + out.T(out.ThumbsDown, "Unable to pick a default driver. Here is what was considered, in preference order:") + for _, r := range rejects { + out.T(out.Option, "{{ .name }}: {{ .rejection }}", out.V{"name": r.Name, "rejection": r.Rejection}) + } + out.T(out.Workaround, "Try specifying a --driver, or see https://minikube.sigs.k8s.io/docs/start/") + os.Exit(exit.Unavailable) } if len(alts) > 1 { diff --git a/pkg/minikube/driver/driver.go b/pkg/minikube/driver/driver.go index ed0cbdee236a..7f67a76fe754 100644 --- a/pkg/minikube/driver/driver.go +++ b/pkg/minikube/driver/driver.go @@ -174,8 +174,8 @@ func Choices(vm bool) []registry.DriverState { return options } -// Suggest returns a suggested driver from a set of options -func Suggest(options []registry.DriverState) (registry.DriverState, []registry.DriverState) { +// Suggest returns a suggested driver, alternate drivers, and rejected drivers +func Suggest(options []registry.DriverState) (registry.DriverState, []registry.DriverState, []registry.DriverState) { pick := registry.DriverState{} for _, ds := range options { if !ds.State.Installed { @@ -198,17 +198,30 @@ func Suggest(options []registry.DriverState) (registry.DriverState, []registry.D } alternates := []registry.DriverState{} + rejects := []registry.DriverState{} for _, ds := range options { if ds != pick { - if !ds.State.Healthy || !ds.State.Installed { + glog.Errorf("%s: %s", ds.Name, ds.Rejection) + if !ds.State.Installed { + ds.Rejection = fmt.Sprintf("Not installed: %v", ds.State.Error) + rejects = append(rejects, ds) continue } + + if !ds.State.Healthy { + ds.Rejection = fmt.Sprintf("Not healthy: %v", ds.State.Error) + rejects = append(rejects, ds) + continue + } + + ds.Rejection = fmt.Sprintf("%s is preferred", pick.Name) alternates = append(alternates, ds) } } glog.Infof("Picked: %+v", pick) glog.Infof("Alternatives: %+v", alternates) - return pick, alternates + glog.Infof("Rejects: %+v", rejects) + return pick, alternates, rejects } // Status returns the status of a driver diff --git a/pkg/minikube/driver/driver_test.go b/pkg/minikube/driver/driver_test.go index 5d0bfd400924..b6afd6a62c9e 100644 --- a/pkg/minikube/driver/driver_test.go +++ b/pkg/minikube/driver/driver_test.go @@ -112,6 +112,7 @@ func TestSuggest(t *testing.T) { choices []string pick string alts []string + rejects []string }{ { def: registry.DriverDef{ @@ -122,6 +123,7 @@ func TestSuggest(t *testing.T) { choices: []string{"unhealthy"}, pick: "", alts: []string{}, + rejects: []string{"unhealthy"}, }, { def: registry.DriverDef{ @@ -132,6 +134,7 @@ func TestSuggest(t *testing.T) { choices: []string{"discouraged", "unhealthy"}, pick: "", alts: []string{"discouraged"}, + rejects: []string{"unhealthy"}, }, { def: registry.DriverDef{ @@ -142,6 +145,7 @@ func TestSuggest(t *testing.T) { choices: []string{"default", "discouraged", "unhealthy"}, pick: "default", alts: []string{"discouraged"}, + rejects: []string{"unhealthy"}, }, { def: registry.DriverDef{ @@ -152,6 +156,7 @@ func TestSuggest(t *testing.T) { choices: []string{"preferred", "default", "discouraged", "unhealthy"}, pick: "preferred", alts: []string{"default", "discouraged"}, + rejects: []string{"unhealthy"}, }, } for _, tc := range tests { @@ -172,7 +177,7 @@ func TestSuggest(t *testing.T) { t.Errorf("choices mismatch (-want +got):\n%s", diff) } - pick, alts := Suggest(got) + pick, alts, rejects := Suggest(got) if pick.Name != tc.pick { t.Errorf("pick = %q, expected %q", pick.Name, tc.pick) } @@ -184,6 +189,15 @@ func TestSuggest(t *testing.T) { if diff := cmp.Diff(gotAlts, tc.alts); diff != "" { t.Errorf("alts mismatch (-want +got):\n%s", diff) } + + gotRejects := []string{} + for _, r := range rejects { + gotRejects = append(gotRejects, r.Name) + } + if diff := cmp.Diff(gotRejects, tc.rejects); diff != "" { + t.Errorf("rejects mismatch (-want +got):\n%s", diff) + } + }) } } diff --git a/pkg/minikube/out/style.go b/pkg/minikube/out/style.go index c67188e12dc3..a8eee7811e0c 100644 --- a/pkg/minikube/out/style.go +++ b/pkg/minikube/out/style.go @@ -68,6 +68,7 @@ var styles = map[StyleEnum]style{ Launch: {Prefix: "🚀 "}, Sad: {Prefix: "😿 "}, ThumbsUp: {Prefix: "👍 "}, + ThumbsDown: {Prefix: "👎 "}, Option: {Prefix: " ▪ ", LowPrefix: lowIndent}, // Indented bullet Command: {Prefix: " ▪ ", LowPrefix: lowIndent}, // Indented bullet LogEntry: {Prefix: " "}, // Indent diff --git a/pkg/minikube/out/style_enum.go b/pkg/minikube/out/style_enum.go index 097f4452dc72..1437b26823a9 100644 --- a/pkg/minikube/out/style_enum.go +++ b/pkg/minikube/out/style_enum.go @@ -41,6 +41,7 @@ const ( Launch Sad ThumbsUp + ThumbsDown Option Command LogEntry diff --git a/pkg/minikube/registry/global.go b/pkg/minikube/registry/global.go index 16ede79a27eb..3f608ef4712c 100644 --- a/pkg/minikube/registry/global.go +++ b/pkg/minikube/registry/global.go @@ -68,6 +68,8 @@ type DriverState struct { Name string Priority Priority State State + // Rejection is why we chose not to use this driver + Rejection string } func (d DriverState) String() string {