Skip to content

Commit 717b738

Browse files
authored
Merge pull request #9365 from ilya-zuyev/gh_7422-reuse_hyperkit_driver
hyperkit driver should be happy with current minimum verison
2 parents a61e091 + 6c65c5d commit 717b738

File tree

8 files changed

+239
-6
lines changed

8 files changed

+239
-6
lines changed

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.15
44

55
require (
66
cloud.google.com/go/storage v1.8.0
7+
github.com/Azure/azure-sdk-for-go v42.3.0+incompatible
78
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 // indirect
89
github.com/Parallels/docker-machine-parallels v1.3.0
910
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect

go.sum

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ github.com/Azure/azure-sdk-for-go v29.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo
5151
github.com/Azure/azure-sdk-for-go v30.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
5252
github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
5353
github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
54+
github.com/Azure/azure-sdk-for-go v42.3.0+incompatible h1:PAHkmPqd/vQV4LJcqzEUM1elCyTMWjbrO8oFMl0dvBE=
5455
github.com/Azure/azure-sdk-for-go v42.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
5556
github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0=
5657
github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0=

pkg/minikube/driver/install.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/pkg/errors"
3131

3232
"k8s.io/klog/v2"
33+
3334
"k8s.io/minikube/pkg/minikube/download"
3435
"k8s.io/minikube/pkg/minikube/out"
3536
"k8s.io/minikube/pkg/minikube/style"
@@ -55,13 +56,12 @@ func InstallOrUpdate(name string, directory string, v semver.Version, interactiv
5556
defer releaser.Release()
5657

5758
exists := driverExists(executable)
58-
path, err := validateDriver(executable, v)
59+
path, err := validateDriver(executable, minAcceptableDriverVersion(name, v))
5960
if !exists || (err != nil && autoUpdate) {
6061
klog.Warningf("%s: %v", executable, err)
6162
path = filepath.Join(directory, executable)
62-
derr := download.Driver(executable, path, v)
63-
if derr != nil {
64-
return derr
63+
if err := download.Driver(executable, path, v); err != nil {
64+
return err
6565
}
6666
}
6767
return fixDriverPermissions(name, path, interactive)
@@ -133,6 +133,8 @@ func validateDriver(executable string, v semver.Version) (string, error) {
133133
if err != nil {
134134
return path, errors.Wrap(err, "can't parse driver version")
135135
}
136+
klog.Infof("%s version is %s", path, driverVersion)
137+
136138
if driverVersion.LT(v) {
137139
return path, fmt.Errorf("%s is version %s, want %s", executable, driverVersion, v)
138140
}

pkg/minikube/driver/version.go

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors All rights reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package driver
18+
19+
import (
20+
"github.com/blang/semver"
21+
"k8s.io/klog/v2"
22+
)
23+
24+
// minHyperkitVersion is the minimum version of the minikube hyperkit driver compatible with the current minikube code
25+
var minHyperkitVersion *semver.Version
26+
27+
const minHyperkitVersionStr = "1.11.0"
28+
29+
func init() {
30+
v, err := semver.New(minHyperkitVersionStr)
31+
if err != nil {
32+
klog.Errorf("Failed to parse the hyperkit driver version: %v", err)
33+
} else {
34+
minHyperkitVersion = v
35+
}
36+
}
37+
38+
// minAcceptableDriverVersion is the minimum version of driver supported by current version of minikube
39+
func minAcceptableDriverVersion(driver string, mkVer semver.Version) semver.Version {
40+
switch driver {
41+
case HyperKit:
42+
if minHyperkitVersion != nil {
43+
return *minHyperkitVersion
44+
}
45+
return mkVer
46+
case KVM2:
47+
return mkVer
48+
default:
49+
klog.Warningf("Unexpected driver: %v", driver)
50+
return mkVer
51+
}
52+
}

pkg/minikube/driver/version_test.go

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors All rights reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package driver
18+
19+
import (
20+
"testing"
21+
22+
"github.com/blang/semver"
23+
)
24+
25+
func Test_minDriverVersion(t *testing.T) {
26+
27+
tests := []struct {
28+
desc string
29+
driver string
30+
mkV string
31+
want semver.Version
32+
}{
33+
{"Hyperkit", HyperKit, "1.1.1", *minHyperkitVersion},
34+
{"Invalid", "_invalid_", "1.1.1", v("1.1.1")},
35+
{"KVM2", KVM2, "1.1.1", v("1.1.1")},
36+
}
37+
for _, tt := range tests {
38+
t.Run(tt.desc, func(t *testing.T) {
39+
if got := minAcceptableDriverVersion(tt.driver, v(tt.mkV)); !got.EQ(tt.want) {
40+
t.Errorf("Invalid min supported version, got: %v, want: %v", got, tt.want)
41+
}
42+
})
43+
}
44+
}
45+
46+
func v(s string) semver.Version {
47+
r, err := semver.New(s)
48+
if err != nil {
49+
panic(err)
50+
}
51+
return *r
52+
}

test/integration/driver_install_or_update_test.go

+125-2
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@ import (
2525
"runtime"
2626
"testing"
2727

28+
"github.com/Azure/azure-sdk-for-go/tools/apidiff/ioext"
2829
"github.com/blang/semver"
2930

3031
"k8s.io/minikube/pkg/minikube/driver"
32+
"k8s.io/minikube/pkg/minikube/localpath"
33+
"k8s.io/minikube/pkg/version"
3134
)
3235

3336
func TestKVMDriverInstallOrUpdate(t *testing.T) {
@@ -158,8 +161,8 @@ func TestHyperKitDriverInstallOrUpdate(t *testing.T) {
158161
t.Fatalf("Expected new semver. test: %v, got: %v", tc.name, err)
159162
}
160163

161-
if err := exec.Command("sudo", "-n", "ls").Run(); err != nil {
162-
t.Skipf("password required to execute 'ls', skipping remaining test: %v", err)
164+
if sudoNeedsPassword() {
165+
t.Skipf("password required to execute 'sudo', skipping remaining test")
163166
}
164167

165168
err = driver.InstallOrUpdate("hyperkit", dir, newerVersion, false, true)
@@ -173,3 +176,123 @@ func TestHyperKitDriverInstallOrUpdate(t *testing.T) {
173176
}
174177
}
175178
}
179+
180+
func TestHyperkitDriverSkipUpgrade(t *testing.T) {
181+
if runtime.GOOS != "darwin" {
182+
t.Skip("Skip if not darwin.")
183+
}
184+
185+
MaybeParallel(t)
186+
tests := []struct {
187+
name string
188+
path string
189+
expectedVersion string
190+
}{
191+
{
192+
name: "upgrade-v1.11.0-to-current",
193+
path: filepath.Join(*testdataDir, "hyperkit-driver-version-1.11.0"),
194+
expectedVersion: "v1.11.0",
195+
},
196+
{
197+
name: "upgrade-v1.2.0-to-current",
198+
path: filepath.Join(*testdataDir, "hyperkit-driver-older-version"),
199+
expectedVersion: version.GetVersion(),
200+
},
201+
}
202+
203+
sudoPath, err := exec.LookPath("sudo")
204+
if err != nil {
205+
t.Fatalf("No sudo in path: %v", err)
206+
}
207+
208+
for _, tc := range tests {
209+
t.Run(tc.name, func(t *testing.T) {
210+
mkDir, drvPath, err := prepareTempMinikubeDirWithHyperkitDriver(tc.name, tc.path)
211+
if err != nil {
212+
t.Fatalf("Failed to prepare tempdir. test: %s, got: %v", tc.name, err)
213+
}
214+
defer func() {
215+
if err := os.RemoveAll(mkDir); err != nil {
216+
t.Errorf("Failed to remove mkDir %q: %v", mkDir, err)
217+
}
218+
}()
219+
220+
cmd := exec.Command(Target(), "start", "--download-only", "--interactive=false", "--driver=hyperkit")
221+
cmd.Stdout = os.Stdout
222+
cmd.Stderr = os.Stdout
223+
cmd.Env = append(os.Environ(),
224+
fmt.Sprintf("PATH=%v%c%v", filepath.Dir(drvPath), filepath.ListSeparator, filepath.Dir(sudoPath)),
225+
"MINIKUBE_HOME="+mkDir)
226+
if err = cmd.Run(); err != nil {
227+
t.Fatalf("failed to run minikube. got: %v", err)
228+
}
229+
230+
upgradedVersion, err := driverVersion(drvPath)
231+
if err != nil {
232+
t.Fatalf("failed to check driver version. got: %v", err)
233+
}
234+
235+
if upgradedVersion != tc.expectedVersion {
236+
t.Fatalf("invalid driver version. expected: %v, got: %v", tc.expectedVersion, upgradedVersion)
237+
}
238+
})
239+
}
240+
}
241+
242+
func sudoNeedsPassword() bool {
243+
err := exec.Command("sudo", "-n", "ls").Run()
244+
return err != nil
245+
}
246+
247+
func driverVersion(path string) (string, error) {
248+
output, err := exec.Command(path, "version").Output()
249+
if err != nil {
250+
return "", err
251+
}
252+
253+
var resultVersion string
254+
_, err = fmt.Sscanf(string(output), "version: %s\n", &resultVersion)
255+
if err != nil {
256+
return "", err
257+
}
258+
return resultVersion, nil
259+
}
260+
261+
// prepareTempMinikubeDirWithHyperkitDriver creates a temp .minikube directory
262+
// with structure essential to testing of hyperkit driver updates
263+
func prepareTempMinikubeDirWithHyperkitDriver(name, driver string) (string, string, error) {
264+
temp, err := ioutil.TempDir("", name)
265+
if err != nil {
266+
return "", "", fmt.Errorf("failed to create tempdir: %v", err)
267+
}
268+
mkDir := filepath.Join(temp, ".minikube")
269+
mkBinDir := filepath.Join(mkDir, "bin")
270+
err = os.MkdirAll(mkBinDir, 0777)
271+
if err != nil {
272+
return "", "", fmt.Errorf("failed to prepare tempdir: %v", err)
273+
}
274+
275+
pwd, err := os.Getwd()
276+
if err != nil {
277+
return "", "", fmt.Errorf("failed to get working directory: %v", err)
278+
}
279+
280+
testDataDriverPath := filepath.Join(pwd, driver, "docker-machine-driver-hyperkit")
281+
if _, err = os.Stat(testDataDriverPath); err != nil {
282+
return "", "", fmt.Errorf("expected driver to exist: %v", err)
283+
}
284+
// copy driver to temp bin
285+
testDriverPath := filepath.Join(mkBinDir, "docker-machine-driver-hyperkit")
286+
if err = ioext.CopyFile(testDataDriverPath, testDriverPath, false); err != nil {
287+
return "", "", fmt.Errorf("failed to setup current hyperkit driver: %v", err)
288+
}
289+
290+
// try to copy cached files to the temp minikube folder to avoid downloading of iso and preloads
291+
_ = ioext.CopyDir(filepath.Join(localpath.MakeMiniPath("cache")), filepath.Join(mkDir, "cache"))
292+
293+
// change permission to allow driver to be executable
294+
if err = os.Chmod(testDriverPath, 0755); err != nil {
295+
return "", "", fmt.Errorf("failed to set driver permission: %v", err)
296+
}
297+
return temp, testDriverPath, nil
298+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Starting minikube version 1.14 we do not update the installed hyperkit driver if its version is 1.11.0 or higher.
2+
Have the hyperkit driver v1.11.0 here to test this behaviour.

0 commit comments

Comments
 (0)