Skip to content

Commit

Permalink
Merge pull request #5085 from josedonizetti/download-kvm2-driver
Browse files Browse the repository at this point in the history
Download kvm2 driver
  • Loading branch information
tstromberg authored Sep 11, 2019
2 parents f36c5d8 + e5cc21c commit da3890c
Show file tree
Hide file tree
Showing 11 changed files with 250 additions and 55 deletions.
12 changes: 12 additions & 0 deletions cmd/minikube/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"fmt"
"io/ioutil"
"os"
"runtime"
"strings"

"github.com/docker/machine/libmachine"
Expand Down Expand Up @@ -108,6 +109,12 @@ func Execute() {
flag.Usage = translate.T(flag.Usage)
})

if runtime.GOOS == "linux" {
// add minikube binaries to the path
targetDir := constants.MakeMiniPath("bin")
addToPath(targetDir)
}

if err := RootCmd.Execute(); err != nil {
// Cobra already outputs the error, typically because the user provided an unknown command.
os.Exit(exit.BadUsage)
Expand Down Expand Up @@ -281,3 +288,8 @@ func getClusterBootstrapper(api libmachine.API, bootstrapperName string) (bootst

return b, nil
}

func addToPath(dir string) {
path := os.Getenv("PATH")
os.Setenv("PATH", fmt.Sprintf("%s:%s", dir, path))
}
44 changes: 17 additions & 27 deletions cmd/minikube/cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"os/exec"
"os/user"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
Expand All @@ -46,6 +45,7 @@ import (
"github.com/spf13/viper"
"golang.org/x/sync/errgroup"
cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config"
"k8s.io/minikube/pkg/drivers"
"k8s.io/minikube/pkg/minikube/bootstrapper"
"k8s.io/minikube/pkg/minikube/bootstrapper/kubeadm"
"k8s.io/minikube/pkg/minikube/cluster"
Expand Down Expand Up @@ -278,7 +278,8 @@ func runStart(cmd *cobra.Command, args []string) {
registryMirror = viper.GetStringSlice("registry_mirror")
}

if err := cmdcfg.IsValidDriver(runtime.GOOS, viper.GetString(vmDriver)); err != nil {
driver := viper.GetString(vmDriver)
if err := cmdcfg.IsValidDriver(runtime.GOOS, driver); err != nil {
exit.WithCodeT(
exit.Failure,
"The driver '{{.driver}}' is not supported on {{.os}}",
Expand All @@ -288,7 +289,7 @@ func runStart(cmd *cobra.Command, args []string) {

validateConfig()
validateUser()
validateDriverVersion(viper.GetString(vmDriver))
validateDriverVersion(driver)

k8sVersion, isUpgrade := getKubernetesVersion()
config, err := generateCfgFromFlags(cmd, k8sVersion)
Expand Down Expand Up @@ -1027,9 +1028,21 @@ func validateDriverVersion(vmDriver string) {
var driverExecutable string
driverDocumentation := fmt.Sprintf("%s%s#driver-installation", constants.DriverDocumentation, vmDriver)

minikubeVersion, err := version.GetSemverVersion()
if err != nil {
out.WarningT("Error parsing minukube version: {{.error}}", out.V{"error": err})
return
}

switch vmDriver {
case constants.DriverKvm2:
driverExecutable = fmt.Sprintf("docker-machine-driver-%s", constants.DriverKvm2)
targetDir := constants.MakeMiniPath("bin")
err := drivers.InstallOrUpdate(driverExecutable, targetDir, minikubeVersion)
if err != nil {
out.WarningT("Error downloading driver: {{.error}}", out.V{"error": err})
}
return
case constants.DriverHyperkit:
driverExecutable = fmt.Sprintf("docker-machine-driver-%s", constants.DriverHyperkit)
default: // driver doesn't support version
Expand All @@ -1046,7 +1059,7 @@ func validateDriverVersion(vmDriver string) {
return
}

v := extractVMDriverVersion(string(output))
v := drivers.ExtractVMDriverVersion(string(output))

// if the driver doesn't have return any version, it is really old, we force a upgrade.
if len(v) == 0 && !viper.GetBool(force) {
Expand All @@ -1063,33 +1076,10 @@ func validateDriverVersion(vmDriver string) {
return
}

minikubeVersion, err := version.GetSemverVersion()
if err != nil {
out.WarningT("Error parsing minikube version: {{.error}}", out.V{"error": err})
return
}

if vmDriverVersion.LT(minikubeVersion) {
out.WarningT(
"The installed version of '{{.driver_executable}}' ({{.driver_version}}) is no longer current. Upgrade: {{.documentation_url}}",
out.V{"driver_executable": driverExecutable, "driver_version": vmDriverVersion, "documentation_url": driverDocumentation},
)
}
}

// extractVMDriverVersion extracts the driver version.
// KVM and Hyperkit drivers support the 'version' command, that display the information as:
// version: vX.X.X
// commit: XXXX
// This method returns the version 'vX.X.X' or empty if the version isn't found.
func extractVMDriverVersion(s string) string {
versionRegex := regexp.MustCompile(`version:(.*)`)
matches := versionRegex.FindStringSubmatch(s)

if len(matches) != 2 {
return ""
}

v := strings.TrimSpace(matches[1])
return strings.TrimPrefix(v, version.VersionPrefix)
}
24 changes: 0 additions & 24 deletions cmd/minikube/cmd/start_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,30 +25,6 @@ import (
"k8s.io/minikube/pkg/minikube/constants"
)

func Test_extractVMDriverVersion(t *testing.T) {
v := extractVMDriverVersion("")
if len(v) != 0 {
t.Error("Expected empty string")
}

v = extractVMDriverVersion("random text")
if len(v) != 0 {
t.Error("Expected empty string")
}

expectedVersion := "1.2.3"

v = extractVMDriverVersion("version: v1.2.3")
if expectedVersion != v {
t.Errorf("Expected version: %s, got: %s", expectedVersion, v)
}

v = extractVMDriverVersion("version: 1.2.3")
if expectedVersion != v {
t.Errorf("Expected version: %s, got: %s", expectedVersion, v)
}
}

func TestGenerateCfgFromFlagsHTTPProxyHandling(t *testing.T) {
viper.SetDefault(memory, constants.DefaultMemorySize)
viper.SetDefault(humanReadableDiskSize, constants.DefaultDiskSize)
Expand Down
2 changes: 1 addition & 1 deletion hack/jenkins/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ gsutil -qm cp \
"gs://minikube-builds/${MINIKUBE_LOCATION}/docker-machine-driver"-* \
"gs://minikube-builds/${MINIKUBE_LOCATION}/e2e-${OS_ARCH}" out

gsutil -qm cp "gs://minikube-builds/${MINIKUBE_LOCATION}/testdata"/* testdata/
gsutil -qm cp -r "gs://minikube-builds/${MINIKUBE_LOCATION}/testdata"/* testdata/

gsutil -qm cp "gs://minikube-builds/${MINIKUBE_LOCATION}/gvisor-addon" testdata/

Expand Down
99 changes: 99 additions & 0 deletions pkg/drivers/drivers.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,29 @@ import (
"io"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"strings"
"syscall"

"github.com/blang/semver"
"github.com/docker/machine/libmachine/drivers"
"github.com/docker/machine/libmachine/mcnflag"
"github.com/docker/machine/libmachine/mcnutils"
"github.com/docker/machine/libmachine/ssh"
"github.com/golang/glog"
"github.com/hashicorp/go-getter"
"github.com/pkg/errors"
"k8s.io/minikube/pkg/version"

"k8s.io/minikube/pkg/minikube/out"
"k8s.io/minikube/pkg/util"
)

const (
driverKVMDownloadURL = "https://storage.googleapis.com/minikube/releases/latest/docker-machine-driver-kvm2"
)

// GetDiskPath returns the path of the machine disk image
Expand Down Expand Up @@ -136,3 +150,88 @@ func fixPermissions(path string) error {
}
return nil
}

// InstallOrUpdate downloads driver if it is not present, or updates it if there's a newer version
func InstallOrUpdate(driver, destination string, minikubeVersion semver.Version) error {
_, err := exec.LookPath(driver)
// if file driver doesn't exist, download it
if err != nil {
return download(driver, destination)
}

cmd := exec.Command(driver, "version")
output, err := cmd.Output()
// if driver doesnt support 'version', it is old, download it
if err != nil {
return download(driver, destination)
}

v := ExtractVMDriverVersion(string(output))

// if the driver doesn't return any version, download it
if len(v) == 0 {
return download(driver, destination)
}

vmDriverVersion, err := semver.Make(v)
if err != nil {
return errors.Wrap(err, "can't parse driver version")
}

// if the current driver version is older, download newer
if vmDriverVersion.LT(minikubeVersion) {
return download(driver, destination)
}

return nil
}

func download(driver, destination string) error {
// only support kvm2 for now
if driver != "docker-machine-driver-kvm2" {
return nil
}

out.T(out.Happy, "Downloading driver {{.driver}}:", out.V{"driver": driver})

targetFilepath := path.Join(destination, "docker-machine-driver-kvm2")
os.Remove(targetFilepath)

url := driverKVMDownloadURL

opts := []getter.ClientOption{getter.WithProgress(util.DefaultProgressBar)}
client := &getter.Client{
Src: url,
Dst: targetFilepath,
Mode: getter.ClientModeFile,
Options: opts,
}

if err := client.Get(); err != nil {
return errors.Wrapf(err, "can't download driver %s from: %s", driver, url)
}

err := os.Chmod(targetFilepath, 0777)
if err != nil {
return errors.Wrap(err, "chmod error")
}

return nil
}

// ExtractVMDriverVersion extracts the driver version.
// KVM and Hyperkit drivers support the 'version' command, that display the information as:
// version: vX.X.X
// commit: XXXX
// This method returns the version 'vX.X.X' or empty if the version isn't found.
func ExtractVMDriverVersion(s string) string {
versionRegex := regexp.MustCompile(`version:(.*)`)
matches := versionRegex.FindStringSubmatch(s)

if len(matches) != 2 {
return ""
}

v := strings.TrimSpace(matches[1])
return strings.TrimPrefix(v, version.VersionPrefix)
}
24 changes: 24 additions & 0 deletions pkg/drivers/drivers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,27 @@ func Test_createDiskImage(t *testing.T) {
t.Errorf("Disk size is %v, want %v", fi.Size(), sizeInBytes)
}
}

func TestExtractVMDriverVersion(t *testing.T) {
v := ExtractVMDriverVersion("")
if len(v) != 0 {
t.Error("Expected empty string")
}

v = ExtractVMDriverVersion("random text")
if len(v) != 0 {
t.Error("Expected empty string")
}

expectedVersion := "1.2.3"

v = ExtractVMDriverVersion("version: v1.2.3")
if expectedVersion != v {
t.Errorf("Expected version: %s, got: %s", expectedVersion, v)
}

v = ExtractVMDriverVersion("version: 1.2.3")
if expectedVersion != v {
t.Errorf("Expected version: %s, got: %s", expectedVersion, v)
}
}
2 changes: 1 addition & 1 deletion pkg/util/downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (f DefaultDownloader) CacheMinikubeISOFromURL(url string) error {
// Predictable temp destination so that resume can function
tmpDst := dst + ".download"

opts := []getter.ClientOption{getter.WithProgress(defaultProgressBar)}
opts := []getter.ClientOption{getter.WithProgress(DefaultProgressBar)}
client := &getter.Client{
Src: urlWithChecksum,
Dst: tmpDst,
Expand Down
4 changes: 2 additions & 2 deletions pkg/util/progressbar.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ limitations under the License.
*/

// This file implements a go-getter wrapper for cheggaaa progress bar

// based on:
// https://github.com/hashicorp/go-getter/blob/master/cmd/go-getter/progress_tracking.go

package util

import (
Expand All @@ -29,7 +29,7 @@ import (
"github.com/hashicorp/go-getter"
)

var defaultProgressBar getter.ProgressTracker = &progressBar{}
var DefaultProgressBar getter.ProgressTracker = &progressBar{}

type progressBar struct {
lock sync.Mutex
Expand Down
Loading

0 comments on commit da3890c

Please sign in to comment.