Merge pull request #21576 from medyagh/verify_aux_driver

verify aux drivers installed correctly and exit nicely if not
pull/21584/head
Medya Ghazizadeh 2025-09-16 18:34:07 -07:00 committed by GitHub
commit 1a676ed723
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 55 additions and 10 deletions

View File

@ -534,6 +534,12 @@ func updateDriver(driverName string) {
if err != nil { if err != nil {
out.WarningT("Error parsing minikube version: {{.error}}", out.V{"error": err}) 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 { } 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}) out.WarningT("Unable to update {{.driver}} driver: {{.error}}", out.V{"driver": driverName, "error": err})
} }
} }

View File

@ -38,6 +38,20 @@ import (
"k8s.io/minikube/pkg/util/lock" "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 // 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 { func InstallOrUpdate(name string, directory string, v semver.Version, interactive bool, autoUpdate bool) error {
if name != driver.KVM2 && name != driver.HyperKit { if name != driver.KVM2 && name != driver.HyperKit {
@ -65,7 +79,14 @@ func InstallOrUpdate(name string, directory string, v semver.Version, interactiv
return err 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 // 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")) klog.Infof("Validating %s, PATH=%s", executable, os.Getenv("PATH"))
path, err := exec.LookPath(executable) path, err := exec.LookPath(executable)
if err != nil { 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 { 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)) ev := extractDriverVersion(string(output))

View File

@ -318,6 +318,10 @@ var (
DrvNotFound = Kind{ID: "DRV_NOT_FOUND", ExitCode: ExDriverNotFound} DrvNotFound = Kind{ID: "DRV_NOT_FOUND", ExitCode: ExDriverNotFound}
// minikube could not find a valid driver // minikube could not find a valid driver
DrvNotDetected = Kind{ID: "DRV_NOT_DETECTED", ExitCode: ExDriverNotFound} 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 // minikube found drivers but none were ready to use
DrvNotHealthy = Kind{ID: "DRV_NOT_HEALTHY", ExitCode: ExDriverNotFound} DrvNotHealthy = Kind{ID: "DRV_NOT_HEALTHY", ExitCode: ExDriverNotFound}
// minikube found the docker driver but the docker service was not running // minikube found the docker driver but the docker service was not running

View File

@ -51,7 +51,6 @@ func TestKVMDriverInstallOrUpdate(t *testing.T) {
name string name string
path 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")}, {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) defer os.Setenv("PATH", originalPath)
for _, tc := range tests { for _, tc := range tests {
dir := t.TempDir() tempDLDir := t.TempDir()
pwd, err := os.Getwd() pwd, err := os.Getwd()
if err != nil { if err != nil {
@ -70,9 +69,19 @@ func TestKVMDriverInstallOrUpdate(t *testing.T) {
_, err = os.Stat(filepath.Join(path, "docker-machine-driver-kvm2")) _, err = os.Stat(filepath.Join(path, "docker-machine-driver-kvm2"))
if err != nil { 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 // change permission to allow driver to be executable
err = os.Chmod(filepath.Join(path, "docker-machine-driver-kvm2"), 0700) err = os.Chmod(filepath.Join(path, "docker-machine-driver-kvm2"), 0700)
if err != nil { if err != nil {
@ -82,17 +91,17 @@ func TestKVMDriverInstallOrUpdate(t *testing.T) {
os.Setenv("PATH", fmt.Sprintf("%s:%s", path, originalPath)) os.Setenv("PATH", fmt.Sprintf("%s:%s", path, originalPath))
// NOTE: This should be a real version, as it impacts the downloaded URL // 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 { if err != nil {
t.Fatalf("Expected new semver. test: %v, got: %v", tc.name, err) 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 { if err != nil {
t.Fatalf("Failed to update driver to %v. test: %s, got: %v", newerVersion, tc.name, err) 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 { if err != nil {
t.Fatalf("Expected driver to be download. test: %s, got: %v", tc.name, err) t.Fatalf("Expected driver to be download. test: %s, got: %v", tc.name, err)
} }