diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index 30a15e91bc..020cd198a9 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -534,6 +534,12 @@ func updateDriver(driverName string) { if err != nil { out.WarningT("Error parsing minikube version: {{.error}}", out.V{"error": err}) } else if err := auxdriver.InstallOrUpdate(driverName, localpath.MakeMiniPath("bin"), v, viper.GetBool(interactive), viper.GetBool(autoUpdate)); err != nil { + if errors.Is(err, auxdriver.ErrAuxDriverVersionCommandFailed) { + exit.Error(reason.DrvAuxNotHealthy, "Aux driver "+driverName, err) + } + if errors.Is(err, auxdriver.ErrAuxDriverVersionNotinPath) { + exit.Error(reason.DrvAuxNotHealthy, "Aux driver"+driverName, err) + } //if failed to update but not a fatal error, log it and continue (old version might still work) out.WarningT("Unable to update {{.driver}} driver: {{.error}}", out.V{"driver": driverName, "error": err}) } } diff --git a/pkg/minikube/driver/auxdriver/install.go b/pkg/minikube/driver/auxdriver/install.go index 76e3b78333..9b41b9f1c7 100644 --- a/pkg/minikube/driver/auxdriver/install.go +++ b/pkg/minikube/driver/auxdriver/install.go @@ -38,6 +38,20 @@ import ( "k8s.io/minikube/pkg/util/lock" ) +func newAuxUnthealthyError(path string) error { + return fmt.Errorf(`failed to execute auxiliary version command "%s --version"`, path) +} + +func newAuxNotFoundError(name, path string) error { + return fmt.Errorf("auxiliary driver %s not found in path %s", name, path) +} + +// ErrAuxDriverVersionCommandFailed indicates the aux driver 'version' command failed to run +var ErrAuxDriverVersionCommandFailed error + +// ErrAuxDriverVersionNotinPath was not found in PATH +var ErrAuxDriverVersionNotinPath error + // InstallOrUpdate downloads driver if it is not present, or updates it if there's a newer version func InstallOrUpdate(name string, directory string, v semver.Version, interactive bool, autoUpdate bool) error { if name != driver.KVM2 && name != driver.HyperKit { @@ -65,7 +79,14 @@ func InstallOrUpdate(name string, directory string, v semver.Version, interactiv return err } } - return fixDriverPermissions(name, path, interactive) + if err := fixDriverPermissions(name, path, interactive); err != nil { + return err + } + + if _, err := validateDriver(executable, minAcceptableDriverVersion(name, v)); err != nil { + return err + } + return nil } // fixDriverPermissions fixes the permissions on a driver @@ -117,12 +138,17 @@ func validateDriver(executable string, v semver.Version) (string, error) { klog.Infof("Validating %s, PATH=%s", executable, os.Getenv("PATH")) path, err := exec.LookPath(executable) if err != nil { - return path, err + klog.Warningf("driver not in path : %s, %v", path, err.Error()) + ErrAuxDriverVersionNotinPath = newAuxNotFoundError(executable, path) + return path, ErrAuxDriverVersionNotinPath } - output, err := exec.Command(path, "version").Output() + cmd := exec.Command(path, "version") + output, err := cmd.CombinedOutput() if err != nil { - return path, err + klog.Warningf("%s failed: %v: %s", cmd, err, output) + ErrAuxDriverVersionCommandFailed = newAuxUnthealthyError(path) + return path, ErrAuxDriverVersionCommandFailed } ev := extractDriverVersion(string(output)) diff --git a/pkg/minikube/reason/reason.go b/pkg/minikube/reason/reason.go index 96e2c54b57..14bc96d389 100644 --- a/pkg/minikube/reason/reason.go +++ b/pkg/minikube/reason/reason.go @@ -318,6 +318,10 @@ var ( DrvNotFound = Kind{ID: "DRV_NOT_FOUND", ExitCode: ExDriverNotFound} // minikube could not find a valid driver DrvNotDetected = Kind{ID: "DRV_NOT_DETECTED", ExitCode: ExDriverNotFound} + // aux drivers (kvm or hyperkit) were not found + DrvAuxNotNotFound = Kind{ID: "DRV_AUX_NOT_FOUND", ExitCode: ExDriverNotFound} + // aux drivers (kvm or hyperkit) were found but not healthy + DrvAuxNotHealthy = Kind{ID: "DRV_AUX_NOT_HEALTHY", ExitCode: ExDriverError} // minikube found drivers but none were ready to use DrvNotHealthy = Kind{ID: "DRV_NOT_HEALTHY", ExitCode: ExDriverNotFound} // minikube found the docker driver but the docker service was not running diff --git a/test/integration/driver_install_or_update_test.go b/test/integration/driver_install_or_update_test.go index 81d16c2516..fcb902e6c6 100644 --- a/test/integration/driver_install_or_update_test.go +++ b/test/integration/driver_install_or_update_test.go @@ -51,7 +51,6 @@ func TestKVMDriverInstallOrUpdate(t *testing.T) { name string path string }{ - {name: "driver-without-version-support", path: filepath.Join(*testdataDir, "kvm2-driver-without-version")}, {name: "driver-with-older-version", path: filepath.Join(*testdataDir, "kvm2-driver-older-version")}, } @@ -59,7 +58,7 @@ func TestKVMDriverInstallOrUpdate(t *testing.T) { defer os.Setenv("PATH", originalPath) for _, tc := range tests { - dir := t.TempDir() + tempDLDir := t.TempDir() pwd, err := os.Getwd() if err != nil { @@ -70,9 +69,19 @@ func TestKVMDriverInstallOrUpdate(t *testing.T) { _, err = os.Stat(filepath.Join(path, "docker-machine-driver-kvm2")) if err != nil { - t.Fatalf("Expected driver to exist. test: %s, got: %v", tc.name, err) + t.Fatalf("Expected test data driver to exist. test: %s, got: %v", tc.name, err) } + // copy test data driver into the temp download dir so we can point PATH to it for before/after install + src := filepath.Join(path, "docker-machine-driver-kvm2") + dst := filepath.Join(tempDLDir, "docker-machine-driver-kvm2") + if err = CopyFile(src, dst, false); err != nil { + t.Fatalf("Failed to copy test data driver to temp dir. test: %s, got: %v", tc.name, err) + } + + // point to the copied driver for the rest of the test + path = tempDLDir + // change permission to allow driver to be executable err = os.Chmod(filepath.Join(path, "docker-machine-driver-kvm2"), 0700) if err != nil { @@ -82,17 +91,17 @@ func TestKVMDriverInstallOrUpdate(t *testing.T) { os.Setenv("PATH", fmt.Sprintf("%s:%s", path, originalPath)) // NOTE: This should be a real version, as it impacts the downloaded URL - newerVersion, err := semver.Make("1.3.0") + newerVersion, err := semver.Make("1.37.0") if err != nil { t.Fatalf("Expected new semver. test: %v, got: %v", tc.name, err) } - err = auxdriver.InstallOrUpdate("kvm2", dir, newerVersion, true, true) + err = auxdriver.InstallOrUpdate("kvm2", tempDLDir, newerVersion, true, true) if err != nil { t.Fatalf("Failed to update driver to %v. test: %s, got: %v", newerVersion, tc.name, err) } - _, err = os.Stat(filepath.Join(dir, "docker-machine-driver-kvm2")) + _, err = os.Stat(filepath.Join(tempDLDir, "docker-machine-driver-kvm2")) if err != nil { t.Fatalf("Expected driver to be download. test: %s, got: %v", tc.name, err) } diff --git a/test/integration/testdata/kvm2-driver-without-version/docker-machine-driver-kvm2 b/test/integration/testdata/kvm2-driver-without-version/docker-machine-driver-kvm2 deleted file mode 100755 index 0ce3916bd7..0000000000 Binary files a/test/integration/testdata/kvm2-driver-without-version/docker-machine-driver-kvm2 and /dev/null differ