Repository: kubernetes/minikube
Pull request #13965 (2022-04-15 18:47:42)

GUI: Add basic view
![Screen Shot 2022-04-15 at 11 53 56 AM](https://user-images.githubusercontent.com/44844360/163616023-4de71087-0225-4797-9255-247316e6f584.png)

- Added basic view that just allows the main functions without customization
- Added button to move between basic and advanced view
- Now shows invalid profiles in cluster table
- Fixed SSH console not respecting selected cluster
- Sorted funcs and variables in header file into logical sections


Patch:
diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go
index ff6a2fad9..228d6d449 100644
--- a/cmd/minikube/cmd/start.go
+++ b/cmd/minikube/cmd/start.go
@@ -34,7 +34,6 @@ import (
 
 	"github.com/Delta456/box-cli-maker/v2"
 	"github.com/blang/semver/v4"
-	"github.com/docker/go-connections/nat"
 	"github.com/docker/machine/libmachine/ssh"
 	"github.com/google/go-containerregistry/pkg/authn"
 	"github.com/google/go-containerregistry/pkg/name"
@@ -942,7 +941,7 @@ func validateUser(drvName string) {
 		return
 	}
 
-	out.ErrT(style.Stopped, `The "{{.driver_name}}" driver should not be used with root privileges. If you wish to continue as root, use --force.`, out.V{"driver_name": drvName})
+	out.ErrT(style.Stopped, `The "{{.driver_name}}" driver should not be used with root privileges.`, out.V{"driver_name": drvName})
 	out.ErrT(style.Tip, "If you are running minikube within a VM, consider using --driver=none:")
 	out.ErrT(style.Documentation, "  {{.url}}", out.V{"url": "https://minikube.sigs.k8s.io/docs/reference/drivers/none/"})
 
@@ -1247,22 +1246,26 @@ func validateFlags(cmd *cobra.Command, drvName string) {
 	validateInsecureRegistry()
 }
 
-// validatePorts validates that the --ports are not below 1024 for the host and not outside range
+// This function validates that the --ports are not below 1024 for the host and not outside range
 func validatePorts(ports []string) error {
-	_, portBindingsMap, err := nat.ParsePortSpecs(ports)
-	if err != nil {
-		return errors.Errorf("Sorry, one of the ports provided with --ports flag is not valid %s (%v)", ports, err)
-	}
-	for _, portBindings := range portBindingsMap {
-		for _, portBinding := range portBindings {
-			p, err := strconv.Atoi(portBinding.HostPort)
+	for _, portDuplet := range ports {
+		parts := strings.Split(portDuplet, ":")
+		if len(parts) > 2 {
+			ip := parts[0]
+			if net.ParseIP(ip) == nil {
+				return errors.Errorf("Sorry, the IP address provided with --ports flag is invalid: %s", ip)
+			}
+			parts = parts[1:]
+		}
+		for i, port := range parts {
+			p, err := strconv.Atoi(port)
 			if err != nil {
 				return errors.Errorf("Sorry, one of the ports provided with --ports flag is not valid %s", ports)
 			}
 			if p > 65535 || p < 1 {
 				return errors.Errorf("Sorry, one of the ports provided with --ports flag is outside range %s", ports)
 			}
-			if detect.IsMicrosoftWSL() && p < 1024 {
+			if detect.IsMicrosoftWSL() && p < 1024 && i == 0 {
 				return errors.Errorf("Sorry, you cannot use privileged ports on the host (below 1024) %s", ports)
 			}
 		}
diff --git a/go.mod b/go.mod
index da0bfc4cb..9d9f5e2e4 100644
--- a/go.mod
+++ b/go.mod
@@ -7,7 +7,7 @@ require (
 	contrib.go.opencensus.io/exporter/stackdriver v0.13.10
 	github.com/Delta456/box-cli-maker/v2 v2.2.2
 	github.com/GoogleCloudPlatform/docker-credential-gcr v0.0.0-20210713212222-faed5e8b8ca2
-	github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.4.0
+	github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.3.0
 	github.com/Microsoft/hcsshim v0.8.17 // indirect
 	github.com/Parallels/docker-machine-parallels/v2 v2.0.1
 	github.com/VividCortex/godaemon v1.0.0
@@ -106,7 +106,7 @@ require (
 	cloud.google.com/go/compute v1.5.0 // indirect
 	cloud.google.com/go/iam v0.3.0 // indirect
 	cloud.google.com/go/monitoring v1.1.0 // indirect
-	cloud.google.com/go/trace v1.2.0 // indirect
+	cloud.google.com/go/trace v1.0.0 // indirect
 	git.sr.ht/~sbinet/gg v0.3.1 // indirect
 	github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
 	github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect
diff --git a/go.sum b/go.sum
index c12dd0bce..68390dd11 100644
--- a/go.sum
+++ b/go.sum
@@ -37,6 +37,7 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM
 cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
 cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
 cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
+cloud.google.com/go/compute v1.2.0/go.mod h1:xlogom/6gr8RJGBe7nT2eGsQYAFUbbv8dbC29qE3Xmw=
 cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
 cloud.google.com/go/compute v1.5.0 h1:b1zWmYuuHz7gO9kDcM/EpHGr06UgsYNRpNJzI2kFiLM=
 cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
@@ -58,9 +59,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
 cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
 cloud.google.com/go/storage v1.22.0 h1:NUV0NNp9nkBuW66BFRLuMgldN60C57ET3dhbwLIYio8=
 cloud.google.com/go/storage v1.22.0/go.mod h1:GbaLEoMqbVm6sx3Z0R++gSiBlgMv6yUi2q1DeGFKQgE=
+cloud.google.com/go/trace v1.0.0 h1:laKx2y7IWMjguCe5zZx6n7qLtREk4kyE69SXVC0VSN8=
 cloud.google.com/go/trace v1.0.0/go.mod h1:4iErSByzxkyHWzzlAj63/Gmjz0NH1ASqhJguHpGcr6A=
-cloud.google.com/go/trace v1.2.0 h1:oIaB4KahkIUOpLSAAjEJ8y2desbjY/x/RfP4O3KAtTI=
-cloud.google.com/go/trace v1.2.0/go.mod h1:Wc8y/uYyOhPy12KEnXG9XGrvfMz5F5SrYecQlbW1rwM=
 contrib.go.opencensus.io/exporter/stackdriver v0.13.10 h1:a9+GZPUe+ONKUwULjlEOucMMG0qfSCCenlji0Nhqbys=
 contrib.go.opencensus.io/exporter/stackdriver v0.13.10/go.mod h1:I5htMbyta491eUxufwwZPQdcKvvgzMB4O9ni41YnIM8=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
@@ -102,8 +102,8 @@ github.com/Delta456/box-cli-maker/v2 v2.2.2 h1:CpSLcPgi5pY4+arzpyuWN2+nU8gHqto2Y
 github.com/Delta456/box-cli-maker/v2 v2.2.2/go.mod h1:idItIMZeyx3bg73XwSgsLeZd+gdpD2IvGbR3FC8a9TU=
 github.com/GoogleCloudPlatform/docker-credential-gcr v0.0.0-20210713212222-faed5e8b8ca2 h1:rMamBsR6iCT9Y5m2Il6vFGJvY7FAgck4AoA/LobheKU=
 github.com/GoogleCloudPlatform/docker-credential-gcr v0.0.0-20210713212222-faed5e8b8ca2/go.mod h1:BB1eHdMLYEFuFdBlRMb0N7YGVdM5s6Pt0njxgvfbGGs=
-github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.4.0 h1:0jFkxz0dzGjRZItXVhv9U4yJW7Xkr82b1vSUcnD2Zh0=
-github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.4.0/go.mod h1:1KabLpTVwm4YmU74LP4uCrOSP176G5WTMgdvfrJKgLU=
+github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.3.0 h1:JLLDOHEcoREA54hzOnjr8KQcZCvX0E8KhosjE0F1jaQ=
+github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.3.0/go.mod h1:Pe8G2QFgCaohbU/zHRBjn0YaFh9z8/HtuEDh/Lyo04E=
 github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU=
 github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
 github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
@@ -409,6 +409,7 @@ github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
 github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
 github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o=
+github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
 github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
@@ -449,9 +450,11 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7
 github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
 github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
 github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
 github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI=
 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
 github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
 github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro=
@@ -602,6 +605,7 @@ github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97Dwqy
 github.com/googleapis/go-type-adapters v1.0.0 h1:9XdMn+d/G57qq1s8dNc5IesGCXHf6V2HZ2JwRxfA2tA=
 github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
 github.com/googleinterns/cloud-operations-api-mock v0.0.0-20200709193332-a1e58c29bdd3 h1:eHv/jVY/JNop1xg2J9cBb4EzyMpWZoNCP1BslSAIkOI=
+github.com/googleinterns/cloud-operations-api-mock v0.0.0-20200709193332-a1e58c29bdd3/go.mod h1:h/KNeRx7oYU4SpA4SoY7W2/NxDKEEVuwA6j9A27L4OI=
 github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk=
 github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
@@ -1136,20 +1140,31 @@ go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
 go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0=
 go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc=
 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.31.0 h1:woM+Mb4d0A+Dxa3rYPenSN5ZeS9qHUvE8rlObiLRXTY=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.26.0 h1:sdwza9BScvbOFaZLhvKDQc54vQ8CWM8jD9BO2t+rP4E=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.26.0/go.mod h1:4vatbW3QwS11DK0H0SB7FR31/VbthXcYorswdkVXdyg=
 go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=
+go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU=
+go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA=
+go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs=
 go.opentelemetry.io/otel v1.6.3 h1:FLOfo8f9JzFVFVyU+MSRJc2HdEAXQgm7pIv2uFKRSZE=
 go.opentelemetry.io/otel v1.6.3/go.mod h1:7BgNga5fNlF/iZjG06hM3yofffp0ofKCDwSXx1GC4dI=
 go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM=
+go.opentelemetry.io/otel/internal/metric v0.24.0 h1:O5lFy6kAl0LMWBjzy3k//M8VjEaTDWL9DPJuqZmWIAA=
+go.opentelemetry.io/otel/internal/metric v0.24.0/go.mod h1:PSkQG+KuApZjBpC6ea6082ZrWUUy/w132tJ/LOU3TXk=
 go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU=
-go.opentelemetry.io/otel/metric v0.28.0 h1:o5YNh+jxACMODoAo1bI7OES0RUW4jAMae0Vgs2etWAQ=
+go.opentelemetry.io/otel/metric v0.24.0 h1:Rg4UYHS6JKR1Sw1TxnI13z7q/0p/XAbgIqUTagvLJuU=
+go.opentelemetry.io/otel/metric v0.24.0/go.mod h1:tpMFnCD9t+BEGiWY2bWF5+AwjuAdM0lSowQ4SBA3/K4=
 go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw=
 go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc=
+go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs=
 go.opentelemetry.io/otel/sdk v1.6.3 h1:prSHYdwCQOX5DrsEzxowH3nLhoAzEBdZhvrR79scfLs=
 go.opentelemetry.io/otel/sdk v1.6.3/go.mod h1:A4iWF7HTXa+GWL/AaqESz28VuSBIcZ+0CV+IzJ5NMiQ=
 go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE=
 go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE=
 go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw=
+go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk=
+go.opentelemetry.io/otel/trace v1.1.0/go.mod h1:i47XtdcBQiktu5IsrPqOHe8w+sBmnLwwHt8wiUsWGTI=
+go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk=
 go.opentelemetry.io/otel/trace v1.6.3 h1:IqN4L+5b0mPNjdXIiZ90Ni4Bl5BRkDQywePLWemd9bc=
 go.opentelemetry.io/otel/trace v1.6.3/go.mod h1:GNJQusJlUgZl9/TQBPKU/Y/ty+0iVB5fjhKeJGZPGFs=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
@@ -1283,6 +1298,7 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/
 golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
@@ -1450,7 +1466,10 @@ golang.org/x/sys v0.0.0-20211023085530-d6a326fbbf70/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886 h1:eJv7u3ksNXoLbGSKuv2s/SIO4tJVxc/A+MTpzxDgz/Q=
@@ -1526,6 +1545,7 @@ golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roY
 golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200701151220-7cb253f4c4f8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
@@ -1586,7 +1606,9 @@ google.golang.org/api v0.58.0/go.mod h1:cAbP2FsxoGVNwtgNAmmn3y5G1TWAiVYRmg4yku3l
 google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
 google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
 google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
+google.golang.org/api v0.66.0/go.mod h1:I1dmXYpX7HGwz/ejRxwQp2qj5bFAz93HiCU1C1oYd9M=
 google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
+google.golang.org/api v0.68.0/go.mod h1:sOM8pTpwgflXRhz+oC8H2Dr+UcbMqkPPWNJo88Q7TH8=
 google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
 google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
 google.golang.org/api v0.74.0 h1:ExR2D+5TYIrMphWgs5JCgwRhEDlPDXXrLwHHMgPHTXE=
@@ -1628,6 +1650,7 @@ google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfG
 google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20200605102947-12044bf5ea91/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
 google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
 google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
@@ -1669,8 +1692,12 @@ google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ6
 google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220201184016-50beb8ab5c44/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220204002441-d6cc3cc0770e/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220207185906-7721543eae58/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
 google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
 google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
diff --git a/gui/cluster.h b/gui/cluster.h
index 9bb2a59ed..7e4b5fb82 100644
--- a/gui/cluster.h
+++ b/gui/cluster.h
@@ -59,7 +59,6 @@
 #include <QList>
 #include <QMap>
 
-//! [0]
 class Cluster
 {
 public:
@@ -89,12 +88,10 @@ private:
     int m_cpus;
     int m_memory;
 };
-//! [0]
 
 typedef QList<Cluster> ClusterList;
 typedef QHash<QString, Cluster> ClusterHash;
 
-//! [1]
 class ClusterModel : public QAbstractListModel
 {
     Q_OBJECT
@@ -115,6 +112,5 @@ public:
 private:
     ClusterList clusterList;
 };
-//! [1]
 
 #endif // CLUSTER_H
diff --git a/gui/window.cpp b/gui/window.cpp
index 6a2af9939..033309818 100644
--- a/gui/window.cpp
+++ b/gui/window.cpp
@@ -81,6 +81,7 @@
 #include <QStandardPaths>
 #include <QDir>
 #include <QFontDialog>
+#include <QStackedWidget>
 
 #ifndef QT_NO_TERMWIDGET
 #include <QApplication>
@@ -88,16 +89,81 @@
 #include "qtermwidget.h"
 #endif
 
-//! [0]
 Window::Window()
 {
     trayIconIcon = new QIcon(":/images/minikube.png");
     checkForMinikube();
+    isBasicView = true;
+
+    stackedWidget = new QStackedWidget;
+    QVBoxLayout *layout = new QVBoxLayout;
+    dashboardProcess = 0;
+
     createClusterGroupBox();
 
     createActions();
     createTrayIcon();
 
+    createBasicView();
+    createAdvancedView();
+    trayIcon->show();
+    updateButtons();
+    layout->addWidget(stackedWidget);
+    setLayout(layout);
+    resize(200, 250);
+
+    setWindowTitle(tr("minikube"));
+    setWindowIcon(*trayIconIcon);
+}
+
+void Window::createBasicView()
+{
+    basicStartButton = new QPushButton(tr("Start"));
+    basicStopButton = new QPushButton(tr("Stop"));
+    basicDeleteButton = new QPushButton(tr("Delete"));
+    basicRefreshButton = new QPushButton(tr("Refresh"));
+    basicSSHButton = new QPushButton(tr("SSH"));
+    basicDashboardButton = new QPushButton(tr("Dashboard"));
+    QPushButton *advancedViewButton = new QPushButton(tr("Advanced View"));
+
+    QVBoxLayout *buttonLayout = new QVBoxLayout;
+    QGroupBox *catBox = new QGroupBox();
+    catBox->setLayout(buttonLayout);
+    buttonLayout->addWidget(basicStartButton);
+    buttonLayout->addWidget(basicStopButton);
+    buttonLayout->addWidget(basicDeleteButton);
+    buttonLayout->addWidget(basicRefreshButton);
+    buttonLayout->addWidget(basicSSHButton);
+    buttonLayout->addWidget(basicDashboardButton);
+    buttonLayout->addWidget(advancedViewButton);
+    catBox->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
+    stackedWidget->addWidget(catBox);
+
+    connect(basicSSHButton, &QAbstractButton::clicked, this, &Window::sshConsole);
+    connect(basicDashboardButton, &QAbstractButton::clicked, this, &Window::dashboardBrowser);
+    connect(basicStartButton, &QAbstractButton::clicked, this, &Window::startSelectedMinikube);
+    connect(basicStopButton, &QAbstractButton::clicked, this, &Window::stopMinikube);
+    connect(basicDeleteButton, &QAbstractButton::clicked, this, &Window::deleteMinikube);
+    connect(basicRefreshButton, &QAbstractButton::clicked, this, &Window::updateClusters);
+    connect(advancedViewButton, &QAbstractButton::clicked, this, &Window::toAdvancedView);
+}
+
+void Window::toAdvancedView()
+{
+    isBasicView = false;
+    stackedWidget->setCurrentIndex(1);
+    resize(600, 400);
+}
+
+void Window::toBasicView()
+{
+    isBasicView = true;
+    stackedWidget->setCurrentIndex(0);
+    resize(200, 250);
+}
+
+void Window::createAdvancedView()
+{
     connect(sshButton, &QAbstractButton::clicked, this, &Window::sshConsole);
     connect(dashboardButton, &QAbstractButton::clicked, this, &Window::dashboardBrowser);
     connect(startButton, &QAbstractButton::clicked, this, &Window::startSelectedMinikube);
@@ -107,30 +173,17 @@ Window::Window()
     connect(createButton, &QAbstractButton::clicked, this, &Window::initMachine);
     connect(trayIcon, &QSystemTrayIcon::messageClicked, this, &Window::messageClicked);
 
-    dashboardProcess = 0;
-
-    QVBoxLayout *mainLayout = new QVBoxLayout;
-    mainLayout->addWidget(clusterGroupBox);
-    setLayout(mainLayout);
-
-    trayIcon->show();
-
-    setWindowTitle(tr("minikube"));
-    setWindowIcon(*trayIconIcon);
-    resize(600, 400);
+    clusterGroupBox->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
+    stackedWidget->addWidget(clusterGroupBox);
 }
-//! [0]
 
-//! [1]
 void Window::setVisible(bool visible)
 {
     minimizeAction->setEnabled(visible);
     restoreAction->setEnabled(!visible);
     QDialog::setVisible(visible);
 }
-//! [1]
 
-//! [2]
 void Window::closeEvent(QCloseEvent *event)
 {
 #ifdef Q_OS_OSX
@@ -148,16 +201,13 @@ void Window::closeEvent(QCloseEvent *event)
         event->ignore();
     }
 }
-//! [2]
 
-//! [6]
 void Window::messageClicked()
 {
     QMessageBox::information(0, tr("Systray"),
                              tr("Sorry, I already gave what help I could.\n"
                                 "Maybe you should try asking a human?"));
 }
-//! [6]
 
 void Window::createActions()
 {
@@ -240,15 +290,13 @@ ClusterList Window::getClusters()
     ClusterList clusters;
     QStringList args = { "profile", "list", "-o", "json" };
     QString text;
-    bool success = sendMinikubeCommand(args, text);
+    sendMinikubeCommand(args, text);
     QStringList lines;
-    if (success) {
 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
-        lines = text.split("\n", Qt::SkipEmptyParts);
+    lines = text.split("\n", Qt::SkipEmptyParts);
 #else
-        lines = text.split("\n", QString::SkipEmptyParts);
+    lines = text.split("\n", QString::SkipEmptyParts);
 #endif
-    }
     for (int i = 0; i < lines.size(); i++) {
         QString line = lines.at(i);
         QJsonParseError error;
@@ -257,58 +305,67 @@ ClusterList Window::getClusters()
             qDebug() << error.errorString();
             continue;
         }
-        if (json.isObject()) {
-            QJsonObject par = json.object();
-            QJsonArray a = par["valid"].toArray();
-            for (int j = 0; j < a.size(); j++) {
-                QJsonObject obj = a[j].toObject();
-                QString name;
-                if (obj.contains("Name")) {
-                    name = obj["Name"].toString();
-                }
-                if (name.isEmpty()) {
-                    continue;
-                }
-                Cluster cluster(name);
-                if (obj.contains("Status")) {
-                    QString status = obj["Status"].toString();
-                    cluster.setStatus(status);
-                }
-                if (!obj.contains("Config")) {
-                    clusters << cluster;
-                    continue;
-                }
-                QJsonObject config = obj["Config"].toObject();
-                if (config.contains("CPUs")) {
-                    int cpus = config["CPUs"].toInt();
-                    cluster.setCpus(cpus);
-                }
-                if (config.contains("Memory")) {
-                    int memory = config["Memory"].toInt();
-                    cluster.setMemory(memory);
-                }
-                if (config.contains("Driver")) {
-                    QString driver = config["Driver"].toString();
-                    cluster.setDriver(driver);
-                }
-                if (!config.contains("KubernetesConfig")) {
-                    clusters << cluster;
-                    continue;
-                }
-                QJsonObject k8sConfig = config["KubernetesConfig"].toObject();
-                if (k8sConfig.contains("ContainerRuntime")) {
-                    QString containerRuntime = k8sConfig["ContainerRuntime"].toString();
-                    cluster.setContainerRuntime(containerRuntime);
-                }
-                clusters << cluster;
-            }
+        if (!json.isObject()) {
+            continue;
+        }
+        QJsonObject par = json.object();
+        QJsonArray a = par["valid"].toArray();
+        QJsonArray b = par["invalid"].toArray();
+        for (int i = 0; i < b.size(); i++) {
+            a.append(b[i]);
+        }
+        for (int i = 0; i < a.size(); i++) {
+            QJsonObject obj = a[i].toObject();
+            Cluster cluster = createClusterObject(obj);
+            clusters << cluster;
         }
     }
     return clusters;
 }
 
+Cluster Window::createClusterObject(QJsonObject obj)
+{
+    QString name;
+    if (obj.contains("Name")) {
+        name = obj["Name"].toString();
+    }
+    Cluster cluster(name);
+    if (obj.contains("Status")) {
+        QString status = obj["Status"].toString();
+        cluster.setStatus(status);
+    }
+    if (!obj.contains("Config")) {
+        return cluster;
+    }
+    QJsonObject config = obj["Config"].toObject();
+    if (config.contains("CPUs")) {
+        int cpus = config["CPUs"].toInt();
+        cluster.setCpus(cpus);
+    }
+    if (config.contains("Memory")) {
+        int memory = config["Memory"].toInt();
+        cluster.setMemory(memory);
+    }
+    if (config.contains("Driver")) {
+        QString driver = config["Driver"].toString();
+        cluster.setDriver(driver);
+    }
+    if (!config.contains("KubernetesConfig")) {
+        return cluster;
+    }
+    QJsonObject k8sConfig = config["KubernetesConfig"].toObject();
+    if (k8sConfig.contains("ContainerRuntime")) {
+        QString containerRuntime = k8sConfig["ContainerRuntime"].toString();
+        cluster.setContainerRuntime(containerRuntime);
+    }
+    return cluster;
+}
+
 QString Window::selectedCluster()
 {
+    if (isBasicView) {
+        return "minikube";
+    }
     QModelIndex index = clusterListView->currentIndex();
     QVariant variant = index.data(Qt::DisplayRole);
     if (variant.isNull()) {
@@ -356,12 +413,13 @@ void Window::createClusterGroupBox()
     createButton = new QPushButton(tr("Create"));
     sshButton = new QPushButton(tr("SSH"));
     dashboardButton = new QPushButton(tr("Dashboard"));
-
-    updateButtons();
+    QPushButton *basicViewButton = new QPushButton(tr("Basic View"));
+    connect(basicViewButton, &QAbstractButton::clicked, this, &Window::toBasicView);
 
     QHBoxLayout *topButtonLayout = new QHBoxLayout;
     topButtonLayout->addWidget(createButton);
     topButtonLayout->addWidget(refreshButton);
+    topButtonLayout->addWidget(basicViewButton);
     topButtonLayout->addSpacing(340);
 
     QHBoxLayout *bottomButtonLayout = new QHBoxLayout;
@@ -379,6 +437,40 @@ void Window::createClusterGroupBox()
 }
 
 void Window::updateButtons()
+{
+    if (isBasicView) {
+        updateBasicButtons();
+    } else {
+        updateAdvancedButtons();
+    }
+}
+
+void Window::updateBasicButtons()
+{
+    Cluster *cluster = new Cluster();
+    ClusterList list = getClusters();
+    for (int i = 0; i < list.length(); i++) {
+        Cluster curr = list[i];
+        if (curr.name() != "minikube") {
+            continue;
+        }
+        cluster = &curr;
+        break;
+    }
+    bool exists = cluster->name() == "minikube";
+    bool isRunning = exists && cluster->status() == "Running";
+    basicStartButton->setEnabled(isRunning == false);
+    basicStopButton->setEnabled(isRunning == true);
+    basicDeleteButton->setEnabled(exists == true);
+    basicDashboardButton->setEnabled(isRunning == true);
+#if __linux__
+    basicSSHButton->setEnabled(isRunning == true);
+#else
+    basicSSHButton->setEnabled(false);
+#endif
+}
+
+void Window::updateAdvancedButtons()
 {
     QString cluster = selectedCluster();
     if (cluster.isEmpty()) {
@@ -441,6 +533,7 @@ bool Window::sendMinikubeCommand(QStringList cmds, QString &text)
     text = process->readAllStandardOutput();
     if (success) {
     } else {
+        qDebug() << text;
         qDebug() << process->readAllStandardError();
     }
     delete process;
@@ -631,7 +724,7 @@ void Window::sshConsole()
     console->setTerminalFont(font);
     console->setColorScheme("Tango");
     console->setShellProgram(program);
-    QStringList args = { "ssh" };
+    QStringList args = { "ssh", "-p", selectedCluster() };
     console->setArgs(args);
     console->startShellProgram();
 
diff --git a/gui/window.h b/gui/window.h
index 1c321edbd..95fc57b80 100644
--- a/gui/window.h
+++ b/gui/window.h
@@ -56,6 +56,7 @@
 
 #include <QSystemTrayIcon>
 #include <QFormLayout>
+#include <QStackedWidget>
 
 #ifndef QT_NO_SYSTEMTRAYICON
 
@@ -79,7 +80,6 @@ QT_END_NAMESPACE
 
 #include "cluster.h"
 
-//! [0]
 class Window : public QDialog
 {
     Q_OBJECT
@@ -98,53 +98,83 @@ private slots:
     void dashboardClose();
 
 private:
-    void createActionGroupBox();
-    void createActions();
+    // Tray icon
     void createTrayIcon();
-    void startMinikube(QStringList args);
-    void startSelectedMinikube();
-    void stopMinikube();
-    void deleteMinikube();
-    ClusterList getClusters();
-    QString selectedCluster();
-    void setSelectedCluster(QString cluster);
-    QTableView *clusterListView;
+    void createActions();
+    QAction *minimizeAction;
+    QAction *restoreAction;
+    QAction *quitAction;
+    QSystemTrayIcon *trayIcon;
+    QMenu *trayIconMenu;
+    QIcon *trayIconIcon;
+
+    // Basic view
+    void createBasicView();
+    void toBasicView();
+    void updateBasicButtons();
+    void basicStartMinikube();
+    void basicStopMinikube();
+    void basicDeleteMinikube();
+    void basicRefreshMinikube();
+    void basicSSHMinikube();
+    void basicDashboardMinikube();
+    QPushButton *basicStartButton;
+    QPushButton *basicStopButton;
+    QPushButton *basicDeleteButton;
+    QPushButton *basicRefreshButton;
+    QPushButton *basicSSHButton;
+    QPushButton *basicDashboardButton;
+
+    // Advanced view
+    void createAdvancedView();
+    void toAdvancedView();
     void createClusterGroupBox();
+    void updateAdvancedButtons();
+    QPushButton *startButton;
+    QPushButton *stopButton;
+    QPushButton *deleteButton;
+    QPushButton *refreshButton;
+    QPushButton *createButton;
+    QPushButton *sshButton;
+    QPushButton *dashboardButton;
     QGroupBox *clusterGroupBox;
-    ClusterModel *clusterModel;
+
+    // Cluster table
+    QString selectedCluster();
+    void setSelectedCluster(QString cluster);
     ClusterHash getClusterHash();
-    bool sendMinikubeCommand(QStringList cmds);
-    bool sendMinikubeCommand(QStringList cmds, QString &text);
+    ClusterList getClusters();
     void updateClusters();
+    ClusterModel *clusterModel;
+    QTableView *clusterListView;
+
+    // Create cluster
     void askCustom();
     void askName();
     QComboBox *driverComboBox;
     QComboBox *containerRuntimeComboBox;
+
+    // Commands
+    void startMinikube(QStringList args);
+    void startSelectedMinikube();
+    void stopMinikube();
+    void deleteMinikube();
+    bool sendMinikubeCommand(QStringList cmds);
+    bool sendMinikubeCommand(QStringList cmds, QString &text);
     void initMachine();
     void sshConsole();
     void dashboardBrowser();
-    void checkForMinikube();
-    void outputFailedStart(QString text);
-    QLabel *createLabel(QString title, QString text, QFormLayout *form, bool isLink);
-    QPushButton *sshButton;
-    QPushButton *dashboardButton;
+    Cluster createClusterObject(QJsonObject obj);
     QProcess *dashboardProcess;
 
-    QPushButton *startButton;
-    QPushButton *stopButton;
-    QPushButton *deleteButton;
-    QPushButton *refreshButton;
-    QPushButton *createButton;
-
-    QAction *minimizeAction;
-    QAction *restoreAction;
-    QAction *quitAction;
+    // Error messaging
+    void outputFailedStart(QString text);
+    QLabel *createLabel(QString title, QString text, QFormLayout *form, bool isLink);
 
-    QSystemTrayIcon *trayIcon;
-    QMenu *trayIconMenu;
-    QIcon *trayIconIcon;
+    void checkForMinikube();
+    QStackedWidget *stackedWidget;
+    bool isBasicView;
 };
-//! [0]
 
 #endif // QT_NO_SYSTEMTRAYICON
 
diff --git a/pkg/addons/addons_gcpauth.go b/pkg/addons/addons_gcpauth.go
index b69a7df27..e1b329cbc 100644
--- a/pkg/addons/addons_gcpauth.go
+++ b/pkg/addons/addons_gcpauth.go
@@ -28,11 +28,10 @@ import (
 	"time"
 
 	gcr_config "github.com/GoogleCloudPlatform/docker-credential-gcr/config"
-	corev1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-
 	"github.com/pkg/errors"
 	"golang.org/x/oauth2/google"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/klog/v2"
 	"k8s.io/minikube/pkg/minikube/assets"
 	"k8s.io/minikube/pkg/minikube/config"
@@ -50,13 +49,10 @@ const (
 	projectPath     = "/var/lib/minikube/google_cloud_project"
 	secretName      = "gcp-auth"
 	namespaceName   = "gcp-auth"
-
-	// readPermission correlates to read-only file system permissions
-	readPermission = "0444"
 )
 
 // enableOrDisableGCPAuth enables or disables the gcp-auth addon depending on the val parameter
-func enableOrDisableGCPAuth(cfg *config.ClusterConfig, name, val string) error {
+func enableOrDisableGCPAuth(cfg *config.ClusterConfig, name string, val string) error {
 	enable, err := strconv.ParseBool(val)
 	if err != nil {
 		return errors.Wrapf(err, "parsing bool: %s", name)
@@ -90,7 +86,8 @@ func enableAddonGCPAuth(cfg *config.ClusterConfig) error {
 
 	// Create a registry secret in every namespace we can find
 	// Always create the pull secret, no matter where we are
-	if err := createPullSecret(cfg, creds); err != nil {
+	err = createPullSecret(cfg, creds)
+	if err != nil {
 		return errors.Wrap(err, "pull secret")
 	}
 
@@ -101,28 +98,29 @@ func enableAddonGCPAuth(cfg *config.ClusterConfig) error {
 	}
 
 	if creds.JSON == nil {
-		out.WarningT("You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file in order to continue. The image pull secret has been imported.")
+		out.WarningT("You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file to in order to continue. The image pull secret has been imported.")
 		return nil
 	}
 
 	// Actually copy the creds over
-	f := assets.NewMemoryAssetTarget(creds.JSON, credentialsPath, readPermission)
+	f := assets.NewMemoryAssetTarget(creds.JSON, credentialsPath, "0444")
 
-	if err := r.Copy(f); err != nil {
+	err = r.Copy(f)
+	if err != nil {
 		return err
 	}
 
 	// First check if the project env var is explicitly set
 	projectEnv := os.Getenv("GOOGLE_CLOUD_PROJECT")
 	if projectEnv != "" {
-		f := assets.NewMemoryAssetTarget([]byte(projectEnv), projectPath, readPermission)
+		f := assets.NewMemoryAssetTarget([]byte(projectEnv), projectPath, "0444")
 		return r.Copy(f)
 	}
 
 	// We're currently assuming gcloud is installed and in the user's path
 	proj, err := exec.Command("gcloud", "config", "get-value", "project").Output()
 	if err == nil && len(proj) > 0 {
-		f := assets.NewMemoryAssetTarget(bytes.TrimSpace(proj), projectPath, readPermission)
+		f := assets.NewMemoryAssetTarget(bytes.TrimSpace(proj), projectPath, "0444")
 		return r.Copy(f)
 	}
 
@@ -134,7 +132,7 @@ func enableAddonGCPAuth(cfg *config.ClusterConfig) error {
 or set the GOOGLE_CLOUD_PROJECT environment variable.`)
 
 	// Copy an empty file in to avoid errors about missing files
-	emptyFile := assets.NewMemoryAssetTarget([]byte{}, projectPath, readPermission)
+	emptyFile := assets.NewMemoryAssetTarget([]byte{}, projectPath, "0444")
 	return r.Copy(emptyFile)
 
 }
@@ -157,7 +155,7 @@ func createPullSecret(cc *config.ClusterConfig, creds *google.Credentials) error
 			return err
 		}
 
-		var dockercfg string
+		dockercfg := ""
 		registries := append(gcr_config.DefaultGCRRegistries[:], gcr_config.DefaultARRegistries[:]...)
 		for _, reg := range registries {
 			dockercfg += fmt.Sprintf(`"https://%s":{"username":"oauth2accesstoken","password":"%s","email":"none"},`, reg, token.AccessToken)
@@ -291,7 +289,8 @@ func refreshExistingPods(cc *config.ClusterConfig) error {
 				_, err = pods.Get(context.TODO(), p.Name, metav1.GetOptions{})
 			}
 
-			if _, err := pods.Create(context.TODO(), &p, metav1.CreateOptions{}); err != nil {
+			_, err = pods.Create(context.TODO(), &p, metav1.CreateOptions{})
+			if err != nil {
 				return err
 			}
 		}
@@ -305,14 +304,15 @@ func disableAddonGCPAuth(cfg *config.ClusterConfig) error {
 	r := cc.CP.Runner
 
 	// Clean up the files generated when enabling the addon
-	creds := assets.NewMemoryAssetTarget([]byte{}, credentialsPath, readPermission)
+	creds := assets.NewMemoryAssetTarget([]byte{}, credentialsPath, "0444")
 	err := r.Remove(creds)
 	if err != nil {
 		return err
 	}
 
-	project := assets.NewMemoryAssetTarget([]byte{}, projectPath, readPermission)
-	if err := r.Remove(project); err != nil {
+	project := assets.NewMemoryAssetTarget([]byte{}, projectPath, "0444")
+	err = r.Remove(project)
+	if err != nil {
 		return err
 	}
 
@@ -332,7 +332,8 @@ func disableAddonGCPAuth(cfg *config.ClusterConfig) error {
 			continue
 		}
 		secrets := client.Secrets(n.Name)
-		if err := secrets.Delete(context.TODO(), secretName, metav1.DeleteOptions{}); err != nil {
+		err := secrets.Delete(context.TODO(), secretName, metav1.DeleteOptions{})
+		if err != nil {
 			klog.Infof("error deleting secret: %v", err)
 		}
 
@@ -346,7 +347,8 @@ func disableAddonGCPAuth(cfg *config.ClusterConfig) error {
 			for i, ps := range sa.ImagePullSecrets {
 				if ps.Name == secretName {
 					sa.ImagePullSecrets = append(sa.ImagePullSecrets[:i], sa.ImagePullSecrets[i+1:]...)
-					if _, err := serviceaccounts.Update(context.TODO(), &sa, metav1.UpdateOptions{}); err != nil {
+					_, err := serviceaccounts.Update(context.TODO(), &sa, metav1.UpdateOptions{})
+					if err != nil {
 						return err
 					}
 					break
@@ -358,7 +360,7 @@ func disableAddonGCPAuth(cfg *config.ClusterConfig) error {
 	return nil
 }
 
-func verifyGCPAuthAddon(cc *config.ClusterConfig, name, val string) error {
+func verifyGCPAuthAddon(cc *config.ClusterConfig, name string, val string) error {
 	enable, err := strconv.ParseBool(val)
 	if err != nil {
 		return errors.Wrapf(err, "parsing bool: %s", name)
@@ -370,12 +372,14 @@ func verifyGCPAuthAddon(cc *config.ClusterConfig, name, val string) error {
 		return ErrSkipThisAddon
 	}
 
-	if err := verifyAddonStatusInternal(cc, name, val, "gcp-auth"); err != nil {
+	err = verifyAddonStatusInternal(cc, name, val, "gcp-auth")
+	if err != nil {
 		return err
 	}
 
 	if Refresh {
-		if err := refreshExistingPods(cc); err != nil {
+		err = refreshExistingPods(cc)
+		if err != nil {
 			return err
 		}
 	}
diff --git a/pkg/minikube/out/out.go b/pkg/minikube/out/out.go
index 5c9680efc..df5d29b64 100644
--- a/pkg/minikube/out/out.go
+++ b/pkg/minikube/out/out.go
@@ -94,7 +94,6 @@ func Step(st style.Enum, format string, a ...V) {
 	outStyled, _ := stylized(st, useColor, format, a...)
 	if JSON {
 		register.PrintStep(outStyled)
-		klog.Info(outStyled)
 		return
 	}
 	register.RecordStep(outStyled)
@@ -155,6 +154,7 @@ func Infof(format string, a ...V) {
 	outStyled, _ := stylized(style.Option, useColor, format, a...)
 	if JSON {
 		register.PrintInfo(outStyled)
+		return
 	}
 	String(outStyled)
 }
@@ -163,9 +163,8 @@ func Infof(format string, a ...V) {
 func String(format string, a ...interface{}) {
 	// Flush log buffer so that output order makes sense
 	klog.Flush()
-	defer klog.Flush()
 
-	if silent || JSON {
+	if silent {
 		klog.Infof(format, a...)
 		return
 	}
@@ -213,6 +212,10 @@ func spinnerString(format string, a ...interface{}) {
 
 // Ln writes a basic formatted string with a newline to stdout
 func Ln(format string, a ...interface{}) {
+	if JSON {
+		klog.Warningf("please use out.T to log steps in JSON")
+		return
+	}
 	String(format+"\n", a...)
 }
 
@@ -226,7 +229,6 @@ func ErrT(st style.Enum, format string, a ...V) {
 func Err(format string, a ...interface{}) {
 	if JSON {
 		register.PrintError(format)
-		klog.Warningf(format, a...)
 		return
 	}
 	register.RecordError(format)
@@ -269,7 +271,6 @@ func WarningT(format string, a ...V) {
 		}
 		st, _ := stylized(style.Warning, useColor, format, a...)
 		register.PrintWarning(st)
-		klog.Warning(st)
 		return
 	}
 	ErrT(style.Warning, format, a...)
diff --git a/pkg/minikube/out/out_reason.go b/pkg/minikube/out/out_reason.go
index bd1ec43e3..7de54ca76 100644
--- a/pkg/minikube/out/out_reason.go
+++ b/pkg/minikube/out/out_reason.go
@@ -20,7 +20,6 @@ package out
 import (
 	"strings"
 
-	"k8s.io/klog/v2"
 	"k8s.io/minikube/pkg/minikube/out/register"
 	"k8s.io/minikube/pkg/minikube/reason"
 	"k8s.io/minikube/pkg/minikube/style"
@@ -36,8 +35,9 @@ func Error(k reason.Kind, format string, a ...V) {
 			"url":    k.URL,
 			"issues": strings.Join(k.IssueURLs(), ","),
 		})
+	} else {
+		displayText(k, format, a...)
 	}
-	displayText(k, format, a...)
 }
 
 // WarnReason shows a warning reason
@@ -45,8 +45,9 @@ func WarnReason(k reason.Kind, format string, a ...V) {
 	if JSON {
 		msg := Fmt(format, a...)
 		register.PrintWarning(msg)
+	} else {
+		displayText(k, format, a...)
 	}
-	displayText(k, format, a...)
 }
 
 // indentMultiLine indents a message if it contains multiple lines
@@ -70,42 +71,33 @@ func displayText(k reason.Kind, format string, a ...V) {
 		st = style.KnownIssue
 	}
 
-	determineOutput(st, format, a...)
+	ErrT(st, format, a...)
 
 	if k.Advice != "" {
 
 		advice := indentMultiLine(Fmt(k.Advice, a...))
-		determineOutput(style.Tip, Fmt("Suggestion: {{.advice}}", V{"advice": advice}))
+		ErrT(style.Tip, Fmt("Suggestion: {{.advice}}", V{"advice": advice}))
 	}
 
 	if k.URL != "" {
-		determineOutput(style.Documentation, "Documentation: {{.url}}", V{"url": k.URL})
+		ErrT(style.Documentation, "Documentation: {{.url}}", V{"url": k.URL})
 	}
 
 	issueURLs := k.IssueURLs()
 	if len(issueURLs) == 1 {
-		determineOutput(style.Issues, "Related issue: {{.url}}", V{"url": issueURLs[0]})
+		ErrT(style.Issues, "Related issue: {{.url}}", V{"url": issueURLs[0]})
 	}
 
 	if len(issueURLs) > 1 {
-		determineOutput(style.Issues, "Related issues:")
+		ErrT(style.Issues, "Related issues:")
 		for _, i := range issueURLs {
-			determineOutput(style.Issue, "{{.url}}", V{"url": i})
+			ErrT(style.Issue, "{{.url}}", V{"url": i})
 		}
 	}
 
 	if k.NewIssueLink {
-		determineOutput(style.Empty, "")
+		ErrT(style.Empty, "")
 		displayGitHubIssueMessage()
 	}
 	Ln("")
 }
-
-func determineOutput(st style.Enum, format string, a ...V) {
-	if !JSON {
-		ErrT(st, format, a...)
-		return
-	}
-	errStyled, _ := stylized(st, useColor, format, a...)
-	klog.Warning(errStyled)
-}
diff --git a/translations/de.json b/translations/de.json
index 3a0f01063..603375617 100644
--- a/translations/de.json
+++ b/translations/de.json
@@ -626,7 +626,6 @@
 	"Test docs have been saved at - {{.path}}": "Test Dokumentate wurden gespeichert in - {{.path}}",
 	"The \"{{.driver_name}}\" driver requires root privileges. Please run minikube using 'sudo minikube --vm-driver={{.driver_name}}": "Der Treiber \"{{.driver_name}}\" benötigt Root-Rechte. Führen Sie minikube aus mit 'sudo minikube --vm-driver = {{.driver_name}}.",
 	"The \"{{.driver_name}}\" driver should not be used with root privileges.": "Der Treiber \"{{.driver_name}}\" sollte nicht mit Root Privilegien gestartet werden.",
-	"The \"{{.driver_name}}\" driver should not be used with root privileges. If you wish to continue as root, use --force.": "",
 	"The \"{{.name}}\" cluster has been deleted.": "Der Cluster \"{{.name}}\" wurde gelöscht.",
 	"The \"{{.name}}\" cluster has been deleted.__1": "Der Cluster \"{{.name}}\" wurde gelöscht.",
 	"The 'none' driver is designed for experts who need to integrate with an existing VM": "Der Treiber \"Keine\" ist für Experten designed, die mit einer existierenden VM integrieren müssen",
@@ -863,7 +862,6 @@
 	"You cannot change the CPUs for an existing minikube cluster. Please first delete the cluster.": "Die Anzahl der CPUs eines existierenden Minikube Clusters kann nicht geändert werden. Bitte löschen Sie den Cluster zuerst.",
 	"You cannot change the disk size for an existing minikube cluster. Please first delete the cluster.": "Die Plattengröße eines existierenden Minikube Clusters kann nicht geändert werden. Bitte löschen Sie den Cluster zuerst.",
 	"You cannot change the memory size for an existing minikube cluster. Please first delete the cluster.": "Die Speichergröße eines existierenden Minikube Clusters kann nicht geändert werden. Bitte löschen Sie den Cluster zuerst.",
-	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file in order to continue. The image pull secret has been imported.": "",
 	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file to in order to continue. The image pull secret has been imported.": "Sie haben sich mit einem Service Account authentifiziert, welcher kein zugehöriges JSON besitzt. GCP Auth benötigt Zugangsdaten in einer JSON-Datei um weitermachen zu können. Das Image Pull Secret wurde importiert.",
 	"You have chosen to disable the CNI but the \\\"{{.name}}\\\" container runtime requires CNI": "Sie haben den CNI Treiber deaktiviert, aber die \\\"{{.name}}\\\" Container Laufzeitumgebung benötigt ein CNI",
 	"You have selected \"virtualbox\" driver, but there are better options !\nFor better performance and support consider using a different driver: {{.drivers}}\n\nTo turn off this warning run:\n\n\t$ minikube config set WantVirtualBoxDriverWarning false\n\n\nTo learn more about on minikube drivers checkout https://minikube.sigs.k8s.io/docs/drivers/\nTo see benchmarks checkout https://minikube.sigs.k8s.io/docs/benchmarks/cpuusage/\n\n": "Sie haben den \"virtualbox\" Treiber ausgewählt, aber es existieren bessere Möglichkeiten !\nFür eine bessere Performanz und besseren Support erwägen Sie die Verwendung eines anderen Treibers: {{.drivers}}\n\nUm diese Warnung zu deaktivieren, führen Sie folgendes aus:\n\n\t$ minikube config set WantVirtualBoxDriverWarning false\n\n\nUm mehr über die Minikube-Treiber zu erfahren, lesen Sie https://minikube.sigs.k8s.io/docs/drivers/\nZu Benchmarks lesen Sie https://minikube.sigs.k8s.io/docs/benchmarks/cpuusage/\n\n",
diff --git a/translations/es.json b/translations/es.json
index 7e034b806..67b95eef1 100644
--- a/translations/es.json
+++ b/translations/es.json
@@ -633,7 +633,6 @@
 	"Test docs have been saved at - {{.path}}": "",
 	"The \"{{.driver_name}}\" driver requires root privileges. Please run minikube using 'sudo minikube --vm-driver={{.driver_name}}": "El controlador \"{{.driver_name}}\" requiere privilegios de raíz. Ejecuta minikube mediante sudo minikube --vm-driver={{.driver_name}}",
 	"The \"{{.driver_name}}\" driver should not be used with root privileges.": "",
-	"The \"{{.driver_name}}\" driver should not be used with root privileges. If you wish to continue as root, use --force.": "",
 	"The \"{{.name}}\" cluster has been deleted.": "Se ha eliminado el clúster \"{{.name}}\".",
 	"The \"{{.name}}\" cluster has been deleted.__1": "Se ha eliminado el clúster \"{{.name}}\".",
 	"The 'none' driver is designed for experts who need to integrate with an existing VM": "",
@@ -867,7 +866,7 @@
 	"You cannot change the CPUs for an existing minikube cluster. Please first delete the cluster.": "",
 	"You cannot change the disk size for an existing minikube cluster. Please first delete the cluster.": "",
 	"You cannot change the memory size for an existing minikube cluster. Please first delete the cluster.": "",
-	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file in order to continue. The image pull secret has been imported.": "",
+	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file to in order to continue. The image pull secret has been imported.": "",
 	"You have chosen to disable the CNI but the \\\"{{.name}}\\\" container runtime requires CNI": "",
 	"You have selected \"virtualbox\" driver, but there are better options !\nFor better performance and support consider using a different driver: {{.drivers}}\n\nTo turn off this warning run:\n\n\t$ minikube config set WantVirtualBoxDriverWarning false\n\n\nTo learn more about on minikube drivers checkout https://minikube.sigs.k8s.io/docs/drivers/\nTo see benchmarks checkout https://minikube.sigs.k8s.io/docs/benchmarks/cpuusage/\n\n": "",
 	"You may need to manually remove the \"{{.name}}\" VM from your hypervisor": "Puede que tengas que retirar manualmente la VM \"{{.name}}\" de tu hipervisor",
diff --git a/translations/fr.json b/translations/fr.json
index 0bcb0ecbd..c635f9903 100644
--- a/translations/fr.json
+++ b/translations/fr.json
@@ -611,7 +611,6 @@
 	"Target {{.path}} can not be empty": "La cible {{.path}} ne peut pas être vide",
 	"Test docs have been saved at - {{.path}}": "Les documents de test ont été enregistrés à - {{.path}}",
 	"The \"{{.driver_name}}\" driver should not be used with root privileges.": "Le pilote \"{{.driver_name}}\" ne doit pas être utilisé avec les privilèges root.",
-	"The \"{{.driver_name}}\" driver should not be used with root privileges. If you wish to continue as root, use --force.": "",
 	"The 'none' driver is designed for experts who need to integrate with an existing VM": "Le pilote 'none' est conçu pour les experts qui doivent s'intégrer à une machine virtuelle existante",
 	"The '{{.addonName}}' addon is enabled": "Le module '{{.addonName}}' est activé",
 	"The '{{.driver}}' driver requires elevated permissions. The following commands will be executed:\\n\\n{{ .example }}\\n": "Le pilote '{{.driver}}' nécessite des autorisations élevées. Les commandes suivantes seront exécutées :\\n\\n{{ .example }}\\n",
@@ -828,7 +827,6 @@
 	"You cannot change the CPUs for an existing minikube cluster. Please first delete the cluster.": "Vous ne pouvez pas modifier les processeurs d'un cluster minikube existant. Veuillez d'abord supprimer le cluster.",
 	"You cannot change the disk size for an existing minikube cluster. Please first delete the cluster.": "Vous ne pouvez pas modifier la taille du disque pour un cluster minikube existant. Veuillez d'abord supprimer le cluster.",
 	"You cannot change the memory size for an existing minikube cluster. Please first delete the cluster.": "Vous ne pouvez pas modifier la taille de la mémoire d'un cluster minikube existant. Veuillez d'abord supprimer le cluster.",
-	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file in order to continue. The image pull secret has been imported.": "",
 	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file to in order to continue. The image pull secret has been imported.": "Vous vous êtes authentifié avec un compte de service qui n'a pas de JSON associé. L'authentification GCP nécessite des informations d'identification avec un fichier JSON pour continuer. Le secret d'extraction d'image a été importé.",
 	"You have chosen to disable the CNI but the \\\"{{.name}}\\\" container runtime requires CNI": "Vous avez choisi de désactiver le CNI mais le runtime du conteneur \\\"{{.name}}\\\" nécessite CNI",
 	"You have selected \"virtualbox\" driver, but there are better options !\nFor better performance and support consider using a different driver: {{.drivers}}\n\nTo turn off this warning run:\n\n\t$ minikube config set WantVirtualBoxDriverWarning false\n\n\nTo learn more about on minikube drivers checkout https://minikube.sigs.k8s.io/docs/drivers/\nTo see benchmarks checkout https://minikube.sigs.k8s.io/docs/benchmarks/cpuusage/\n\n": "Vous avez sélectionné le pilote \"virtualbox\", mais il existe de meilleures options !\nPour de meilleures performances et une meilleure assistance, envisagez d'utiliser un autre pilote: {{.drivers}}\n\nPour désactiver cet avertissement, exécutez :\n\n\t $ minikube config set WantVirtualBoxDriverWarning false\n\n\nPour en savoir plus sur les pilotes minikube, consultez https://minikube.sigs.k8s.io/docs/drivers/\nPour voir les benchmarks, consultez https://minikube.sigs.k8s. io/docs/benchmarks/cpuusage/\n\n",
diff --git a/translations/ja.json b/translations/ja.json
index a8c62fbd5..4e096f3e8 100644
--- a/translations/ja.json
+++ b/translations/ja.json
@@ -625,7 +625,6 @@
 	"Test docs have been saved at - {{.path}}": "テストドキュメントは {{.path}} に保存されました",
 	"The \"{{.driver_name}}\" driver requires root privileges. Please run minikube using 'sudo minikube --vm-driver={{.driver_name}}": "「{{.driver_name}}」ドライバーにはルート権限が必要です。'sudo minikube --vm-driver={{.driver_name}}' を使用して minikube を実行してください",
 	"The \"{{.driver_name}}\" driver should not be used with root privileges.": "「{{.driver_name}}」ドライバーは root 権限で使用すべきではありません。",
-	"The \"{{.driver_name}}\" driver should not be used with root privileges. If you wish to continue as root, use --force.": "",
 	"The \"{{.name}}\" cluster has been deleted.": "「{{.name}}」クラスターが削除されました",
 	"The \"{{.name}}\" cluster has been deleted.__1": "「{{.name}}」クラスターが削除されました",
 	"The 'none' driver is designed for experts who need to integrate with an existing VM": "'none' ドライバーは既存 VM の統合が必要なエキスパートに向けて設計されています。",
@@ -871,7 +870,6 @@
 	"You cannot change the CPUs for an existing minikube cluster. Please first delete the cluster.": "既存の minikube クラスターに対して、CPU を変更できません。最初にクラスターを削除してください。",
 	"You cannot change the disk size for an existing minikube cluster. Please first delete the cluster.": "既存の minikube クラスターに対して、ディスクサイズを変更できません。最初にクラスターを削除してください。",
 	"You cannot change the memory size for an existing minikube cluster. Please first delete the cluster.": "既存の minikube クラスターに対して、メモリサイズを変更できません。最初にクラスターを削除してください。",
-	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file in order to continue. The image pull secret has been imported.": "",
 	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file to in order to continue. The image pull secret has been imported.": "関連する JSON がないサービスアカウントで認証しています。GCP Auth は、作業を続行するために JSON ファイル付きクレデンシャルを要求します。イメージ取得シークレットがインポートされました。",
 	"You have chosen to disable the CNI but the \\\"{{.name}}\\\" container runtime requires CNI": "CNI 無効が選択されましたが、「{{.name}}」コンテナランタイムは CNI が必要です",
 	"You have selected \"virtualbox\" driver, but there are better options !\nFor better performance and support consider using a different driver: {{.drivers}}\n\nTo turn off this warning run:\n\n\t$ minikube config set WantVirtualBoxDriverWarning false\n\n\nTo learn more about on minikube drivers checkout https://minikube.sigs.k8s.io/docs/drivers/\nTo see benchmarks checkout https://minikube.sigs.k8s.io/docs/benchmarks/cpuusage/\n\n": "「virtualbox」ドライバーが選択されましたが、より良い選択肢があります！\n性能と機能の向上のため、別のドライバー使用を検討してください: {{.drivers}}\n\nこの警告を表示させないためには、以下を実行してください:\n\n\t$ minikube config set WantVirtualBoxDriverWarning false\n\n\nminikube ドライバーについてもっと知るためには、https://minikube.sigs.k8s.io/docs/drivers/ を確認してください。\nベンチマークについては https://minikube.sigs.k8s.io/docs/benchmarks/cpuusage/ を確認してください\n\n",
diff --git a/translations/ko.json b/translations/ko.json
index 1003278cb..17f58969d 100644
--- a/translations/ko.json
+++ b/translations/ko.json
@@ -649,7 +649,6 @@
 	"Test docs have been saved at - {{.path}}": "",
 	"The \"{{.driver_name}}\" driver requires root privileges. Please run minikube using 'sudo minikube --driver={{.driver_name}}'.": "\"{{.driver_name}}\" 드라이버는 root 권한으로 실행되어야 합니다. minikube 를 다음과 같이 실행하세요 'sudo minikube --driver={{.driver_name}}'",
 	"The \"{{.driver_name}}\" driver should not be used with root privileges.": "\"{{.driver_name}}\" 드라이버는 root 권한으로 실행되면 안 됩니다",
-	"The \"{{.driver_name}}\" driver should not be used with root privileges. If you wish to continue as root, use --force.": "",
 	"The 'none' driver is designed for experts who need to integrate with an existing VM": "",
 	"The '{{.addonName}}' addon is enabled": "'{{.addonName}}' 애드온이 활성화되었습니다",
 	"The '{{.driver}}' driver requires elevated permissions. The following commands will be executed:\\n\\n{{ .example }}\\n": "",
@@ -868,7 +867,7 @@
 	"You cannot change the CPUs for an existing minikube cluster. Please first delete the cluster.": "",
 	"You cannot change the disk size for an existing minikube cluster. Please first delete the cluster.": "",
 	"You cannot change the memory size for an existing minikube cluster. Please first delete the cluster.": "",
-	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file in order to continue. The image pull secret has been imported.": "",
+	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file to in order to continue. The image pull secret has been imported.": "",
 	"You have chosen to disable the CNI but the \\\"{{.name}}\\\" container runtime requires CNI": "",
 	"You have selected \"virtualbox\" driver, but there are better options !\nFor better performance and support consider using a different driver: {{.drivers}}\n\nTo turn off this warning run:\n\n\t$ minikube config set WantVirtualBoxDriverWarning false\n\n\nTo learn more about on minikube drivers checkout https://minikube.sigs.k8s.io/docs/drivers/\nTo see benchmarks checkout https://minikube.sigs.k8s.io/docs/benchmarks/cpuusage/\n\n": "",
 	"You may need to manually remove the \"{{.name}}\" VM from your hypervisor": "",
diff --git a/translations/pl.json b/translations/pl.json
index a2e129e66..b27fbb927 100644
--- a/translations/pl.json
+++ b/translations/pl.json
@@ -649,7 +649,6 @@
 	"The \"{{.cluster_name}}\" cluster has been deleted.": "Klaster \"{{.cluster_name}}\" został usunięty",
 	"The \"{{.driver_name}}\" driver requires root privileges. Please run minikube using 'sudo minikube --vm-driver={{.driver_name}}'.": "Sterownik \"{{.driver_name}}\" wymaga uprawnień root'a. Użyj 'sudo minikube --vm-driver={{.driver_name}}'",
 	"The \"{{.driver_name}}\" driver should not be used with root privileges.": "",
-	"The \"{{.driver_name}}\" driver should not be used with root privileges. If you wish to continue as root, use --force.": "",
 	"The \"{{.name}}\" cluster has been deleted.": "Klaster \"{{.name}}\" został usunięty.",
 	"The 'none' driver is designed for experts who need to integrate with an existing VM": "",
 	"The '{{.addonName}}' addon is enabled": "",
@@ -877,7 +876,7 @@
 	"You cannot change the CPUs for an existing minikube cluster. Please first delete the cluster.": "",
 	"You cannot change the disk size for an existing minikube cluster. Please first delete the cluster.": "",
 	"You cannot change the memory size for an existing minikube cluster. Please first delete the cluster.": "",
-	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file in order to continue. The image pull secret has been imported.": "",
+	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file to in order to continue. The image pull secret has been imported.": "",
 	"You have chosen to disable the CNI but the \\\"{{.name}}\\\" container runtime requires CNI": "",
 	"You have selected \"virtualbox\" driver, but there are better options !\nFor better performance and support consider using a different driver: {{.drivers}}\n\nTo turn off this warning run:\n\n\t$ minikube config set WantVirtualBoxDriverWarning false\n\n\nTo learn more about on minikube drivers checkout https://minikube.sigs.k8s.io/docs/drivers/\nTo see benchmarks checkout https://minikube.sigs.k8s.io/docs/benchmarks/cpuusage/\n\n": "",
 	"You may need to manually remove the \"{{.name}}\" VM from your hypervisor": "",
diff --git a/translations/ru.json b/translations/ru.json
index 20e96c555..9ba76b2df 100644
--- a/translations/ru.json
+++ b/translations/ru.json
@@ -592,7 +592,6 @@
 	"Target {{.path}} can not be empty": "",
 	"Test docs have been saved at - {{.path}}": "",
 	"The \"{{.driver_name}}\" driver should not be used with root privileges.": "",
-	"The \"{{.driver_name}}\" driver should not be used with root privileges. If you wish to continue as root, use --force.": "",
 	"The 'none' driver is designed for experts who need to integrate with an existing VM": "",
 	"The '{{.addonName}}' addon is enabled": "",
 	"The '{{.driver}}' driver requires elevated permissions. The following commands will be executed:\\n\\n{{ .example }}\\n": "",
@@ -802,7 +801,7 @@
 	"You cannot change the CPUs for an existing minikube cluster. Please first delete the cluster.": "",
 	"You cannot change the disk size for an existing minikube cluster. Please first delete the cluster.": "",
 	"You cannot change the memory size for an existing minikube cluster. Please first delete the cluster.": "",
-	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file in order to continue. The image pull secret has been imported.": "",
+	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file to in order to continue. The image pull secret has been imported.": "",
 	"You have chosen to disable the CNI but the \\\"{{.name}}\\\" container runtime requires CNI": "",
 	"You have selected \"virtualbox\" driver, but there are better options !\nFor better performance and support consider using a different driver: {{.drivers}}\n\nTo turn off this warning run:\n\n\t$ minikube config set WantVirtualBoxDriverWarning false\n\n\nTo learn more about on minikube drivers checkout https://minikube.sigs.k8s.io/docs/drivers/\nTo see benchmarks checkout https://minikube.sigs.k8s.io/docs/benchmarks/cpuusage/\n\n": "",
 	"You may need to manually remove the \"{{.name}}\" VM from your hypervisor": "",
diff --git a/translations/strings.txt b/translations/strings.txt
index 98672b3c0..db92ea2a1 100644
--- a/translations/strings.txt
+++ b/translations/strings.txt
@@ -592,7 +592,6 @@
 	"Target {{.path}} can not be empty": "",
 	"Test docs have been saved at - {{.path}}": "",
 	"The \"{{.driver_name}}\" driver should not be used with root privileges.": "",
-	"The \"{{.driver_name}}\" driver should not be used with root privileges. If you wish to continue as root, use --force.": "",
 	"The 'none' driver is designed for experts who need to integrate with an existing VM": "",
 	"The '{{.addonName}}' addon is enabled": "",
 	"The '{{.driver}}' driver requires elevated permissions. The following commands will be executed:\\n\\n{{ .example }}\\n": "",
@@ -802,7 +801,7 @@
 	"You cannot change the CPUs for an existing minikube cluster. Please first delete the cluster.": "",
 	"You cannot change the disk size for an existing minikube cluster. Please first delete the cluster.": "",
 	"You cannot change the memory size for an existing minikube cluster. Please first delete the cluster.": "",
-	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file in order to continue. The image pull secret has been imported.": "",
+	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file to in order to continue. The image pull secret has been imported.": "",
 	"You have chosen to disable the CNI but the \\\"{{.name}}\\\" container runtime requires CNI": "",
 	"You have selected \"virtualbox\" driver, but there are better options !\nFor better performance and support consider using a different driver: {{.drivers}}\n\nTo turn off this warning run:\n\n\t$ minikube config set WantVirtualBoxDriverWarning false\n\n\nTo learn more about on minikube drivers checkout https://minikube.sigs.k8s.io/docs/drivers/\nTo see benchmarks checkout https://minikube.sigs.k8s.io/docs/benchmarks/cpuusage/\n\n": "",
 	"You may need to manually remove the \"{{.name}}\" VM from your hypervisor": "",
diff --git a/translations/zh-CN.json b/translations/zh-CN.json
index 804609078..20a4266ed 100644
--- a/translations/zh-CN.json
+++ b/translations/zh-CN.json
@@ -734,7 +734,6 @@
 	"Test docs have been saved at - {{.path}}": "",
 	"The \"{{.driver_name}}\" driver requires root privileges. Please run minikube using 'sudo minikube --vm-driver={{.driver_name}}": "“{{.driver_name}}”驱动程序需要根权限。请使用“sudo minikube --vm-driver={{.driver_name}}”运行 minikube",
 	"The \"{{.driver_name}}\" driver should not be used with root privileges.": "",
-	"The \"{{.driver_name}}\" driver should not be used with root privileges. If you wish to continue as root, use --force.": "",
 	"The \"{{.name}}\" cluster has been deleted.": "“{{.name}}”集群已删除。",
 	"The \"{{.name}}\" cluster has been deleted.__1": "“{{.name}}”集群已删除。",
 	"The 'none' driver does not respect the --cpus flag": "'none' 驱动程序不遵循 --cpus 标志",
@@ -986,7 +985,7 @@
 	"You cannot change the CPUs for an existing minikube cluster. Please first delete the cluster.": "",
 	"You cannot change the disk size for an existing minikube cluster. Please first delete the cluster.": "",
 	"You cannot change the memory size for an existing minikube cluster. Please first delete the cluster.": "",
-	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file in order to continue. The image pull secret has been imported.": "",
+	"You have authenticated with a service account that does not have an associated JSON. The GCP Auth requires credentials with a JSON file to in order to continue. The image pull secret has been imported.": "",
 	"You have chosen to disable the CNI but the \\\"{{.name}}\\\" container runtime requires CNI": "",
 	"You have selected \"virtualbox\" driver, but there are better options !\nFor better performance and support consider using a different driver: {{.drivers}}\n\nTo turn off this warning run:\n\n\t$ minikube config set WantVirtualBoxDriverWarning false\n\n\nTo learn more about on minikube drivers checkout https://minikube.sigs.k8s.io/docs/drivers/\nTo see benchmarks checkout https://minikube.sigs.k8s.io/docs/benchmarks/cpuusage/\n\n": "",
 	"You may need to manually remove the \"{{.name}}\" VM from your hypervisor": "您可能需要从管理程序中手动移除“{{.name}}”虚拟机",


Test patch:
diff --git a/cmd/minikube/cmd/start_test.go b/cmd/minikube/cmd/start_test.go
index 0ce1ce971..5deda2938 100644
--- a/cmd/minikube/cmd/start_test.go
+++ b/cmd/minikube/cmd/start_test.go
@@ -462,126 +462,40 @@ func TestValidateRuntime(t *testing.T) {
 }
 
 func TestValidatePorts(t *testing.T) {
-	isMicrosoftWSL := detect.IsMicrosoftWSL()
 	type portTest struct {
-		// isTarget indicates whether or not the test case is covered
-		// because validatePorts behaves differently depending on whether process is running in WSL in windows or not.
-		isTarget bool
 		ports    []string
 		errorMsg string
 	}
 	var tests = []portTest{
 		{
-			isTarget: true,
-			ports:    []string{"8080:80"},
-			errorMsg: "",
-		},
-		{
-			isTarget: true,
-			ports:    []string{"8080:80/tcp", "8080:80/udp"},
-			errorMsg: "",
-		},
-		{
-			isTarget: true,
-			ports:    []string{"test:8080"},
-			errorMsg: "Sorry, one of the ports provided with --ports flag is not valid [test:8080] (Invalid hostPort: test)",
+			ports:    []string{"test:80"},
+			errorMsg: "Sorry, one of the ports provided with --ports flag is not valid [test:80]",
 		},
 		{
-			isTarget: true,
 			ports:    []string{"0:80"},
 			errorMsg: "Sorry, one of the ports provided with --ports flag is outside range [0:80]",
 		},
 		{
-			isTarget: true,
-			ports:    []string{"0:80/tcp"},
-			errorMsg: "Sorry, one of the ports provided with --ports flag is outside range [0:80/tcp]",
-		},
-		{
-			isTarget: true,
-			ports:    []string{"65536:80/udp"},
-			errorMsg: "Sorry, one of the ports provided with --ports flag is not valid [65536:80/udp] (Invalid hostPort: 65536)",
-		},
-		{
-			isTarget: true,
-			ports:    []string{"0-1:80-81/tcp"},
-			errorMsg: "Sorry, one of the ports provided with --ports flag is outside range [0-1:80-81/tcp]",
-		},
-		{
-			isTarget: true,
-			ports:    []string{"0-1:80-81/udp"},
-			errorMsg: "Sorry, one of the ports provided with --ports flag is outside range [0-1:80-81/udp]",
-		},
-		{
-			isTarget: !isMicrosoftWSL,
-			ports:    []string{"80:80", "1023-1025:8023-8025", "1023-1025:8023-8025/tcp", "1023-1025:8023-8025/udp"},
+			ports:    []string{"8080:80", "6443:443"},
 			errorMsg: "",
 		},
 		{
-			isTarget: isMicrosoftWSL,
-			ports:    []string{"80:80"},
-			errorMsg: "Sorry, you cannot use privileged ports on the host (below 1024) [80:80]",
-		},
-		{
-			isTarget: isMicrosoftWSL,
-			ports:    []string{"1023-1025:8023-8025"},
-			errorMsg: "Sorry, you cannot use privileged ports on the host (below 1024) [1023-1025:8023-8025]",
-		},
-		{
-			isTarget: isMicrosoftWSL,
-			ports:    []string{"1023-1025:8023-8025/tcp"},
-			errorMsg: "Sorry, you cannot use privileged ports on the host (below 1024) [1023-1025:8023-8025/tcp]",
-		},
-		{
-			isTarget: isMicrosoftWSL,
-			ports:    []string{"1023-1025:8023-8025/udp"},
-			errorMsg: "Sorry, you cannot use privileged ports on the host (below 1024) [1023-1025:8023-8025/udp]",
-		},
-		{
-			isTarget: true,
-			ports:    []string{"127.0.0.1:8080:80", "127.0.0.1:8081:80/tcp", "127.0.0.1:8081:80/udp", "127.0.0.1:8082-8083:8082-8083/tcp"},
+			ports:    []string{"127.0.0.1:80:80"},
 			errorMsg: "",
 		},
 		{
-			isTarget: true,
 			ports:    []string{"1000.0.0.1:80:80"},
-			errorMsg: "Sorry, one of the ports provided with --ports flag is not valid [1000.0.0.1:80:80] (Invalid ip address: 1000.0.0.1)",
-		},
-		{
-			isTarget: !isMicrosoftWSL,
-			ports:    []string{"127.0.0.1:80:80", "127.0.0.1:81:81/tcp", "127.0.0.1:81:81/udp", "127.0.0.1:82-83:82-83/tcp", "127.0.0.1:82-83:82-83/udp"},
-			errorMsg: "",
-		},
-		{
-			isTarget: isMicrosoftWSL,
-			ports:    []string{"127.0.0.1:80:80"},
-			errorMsg: "Sorry, you cannot use privileged ports on the host (below 1024) [127.0.0.1:80:80]",
-		},
-		{
-			isTarget: isMicrosoftWSL,
-			ports:    []string{"127.0.0.1:81:81/tcp"},
-			errorMsg: "Sorry, you cannot use privileged ports on the host (below 1024) [127.0.0.1:81:81/tcp]",
-		},
-		{
-			isTarget: isMicrosoftWSL,
-			ports:    []string{"127.0.0.1:81:81/udp"},
-			errorMsg: "Sorry, you cannot use privileged ports on the host (below 1024) [127.0.0.1:81:81/udp]",
-		},
-		{
-			isTarget: isMicrosoftWSL,
-			ports:    []string{"127.0.0.1:80-83:80-83/tcp"},
-			errorMsg: "Sorry, you cannot use privileged ports on the host (below 1024) [127.0.0.1:80-83:80-83/tcp]",
-		},
-		{
-			isTarget: isMicrosoftWSL,
-			ports:    []string{"127.0.0.1:80-83:80-83/udp"},
-			errorMsg: "Sorry, you cannot use privileged ports on the host (below 1024) [127.0.0.1:80-83:80-83/udp]",
+			errorMsg: "Sorry, the IP address provided with --ports flag is invalid: 1000.0.0.1",
 		},
 	}
+	if detect.IsMicrosoftWSL() {
+		tests = append(tests, portTest{
+			ports:    []string{"80:80"},
+			errorMsg: "Sorry, you cannot use privileged ports on the host (below 1024) [80:80]",
+		})
+	}
 	for _, test := range tests {
 		t.Run(strings.Join(test.ports, ","), func(t *testing.T) {
-			if !test.isTarget {
-				return
-			}
 			gotError := ""
 			got := validatePorts(test.ports)
 			if got != nil {