diff --git a/pkg/minikube/machine/cache_binaries.go b/pkg/minikube/machine/cache_binaries.go index e075f8d08c..898540eab3 100644 --- a/pkg/minikube/machine/cache_binaries.go +++ b/pkg/minikube/machine/cache_binaries.go @@ -23,6 +23,7 @@ import ( "path" "runtime" + "github.com/blang/semver" "github.com/golang/glog" "github.com/jimmidyson/go-download" "github.com/pkg/errors" @@ -51,22 +52,40 @@ func CacheBinariesForBootstrapper(version string, clusterBootstrapper string) er return g.Wait() } -// KubernetesReleaseURL gets the location of a kubernetes client -func KubernetesReleaseURL(binaryName, version, osName, archName string) string { +// releaseURL gets the location of a Kubernetes binary +func releaseURL(binaryName, version, osName, archName string) string { return fmt.Sprintf("https://storage.googleapis.com/kubernetes-release/release/%s/bin/%s/%s/%s", version, osName, archName, binaryName) } -// KubernetesReleaseURLSHA1 gets the location of a kubernetes client checksum -func KubernetesReleaseURLSHA1(binaryName, version, osName, archName string) string { - return fmt.Sprintf("%s.sha1", KubernetesReleaseURL(binaryName, version, osName, archName)) +// downloadOptions returns appropriate download options for a +func downloadOptions(url string, version string) (download.FileOptions, error) { + fo := download.FileOptions{ + Mkdirs: download.MkdirAll, + Options: download.Options{ + ChecksumHash: crypto.SHA1, + Checksum: url + ".sha1", + }, + } + + v, err := semver.Make(version[1:]) + if err != nil { + return fo, err + } + + if v.GTE(semver.MustParse("1.17.0")) { + fo.ChecksumHash = crypto.SHA256 + fo.Checksum = url + ".sha256" + } + return fo, nil } // CacheBinary will cache a binary on the host func CacheBinary(binary, version, osName, archName string) (string, error) { + targetDir := localpath.MakeMiniPath("cache", osName, version) targetFilepath := path.Join(targetDir, binary) - url := KubernetesReleaseURL(binary, version, osName, archName) + url := releaseURL(binary, version, osName, archName) _, err := os.Stat(targetFilepath) // If it exists, do no verification and continue @@ -82,16 +101,15 @@ func CacheBinary(binary, version, osName, archName string) (string, error) { return "", errors.Wrapf(err, "mkdir %s", targetDir) } - options := download.FileOptions{ - Mkdirs: download.MkdirAll, + options, err := downloadOptions(url, version) + if err != nil { + return "", errors.Wrap(err, "options") } - - options.Checksum = KubernetesReleaseURLSHA1(binary, version, osName, archName) - options.ChecksumHash = crypto.SHA1 + glog.Infof("Downloading %s: options: %+v", url, options) out.T(out.FileDownload, "Downloading {{.name}} {{.version}}", out.V{"name": binary, "version": version}) if err := download.ToFile(url, targetFilepath, options); err != nil { - return "", errors.Wrapf(err, "Error downloading %s %s", binary, version) + return "", errors.Wrapf(err, url) } if osName == runtime.GOOS && archName == runtime.GOARCH { if err = os.Chmod(targetFilepath, 0755); err != nil { diff --git a/pkg/minikube/machine/cache_binaries_test.go b/pkg/minikube/machine/cache_binaries_test.go index a0ad859662..8b250cafcf 100644 --- a/pkg/minikube/machine/cache_binaries_test.go +++ b/pkg/minikube/machine/cache_binaries_test.go @@ -17,12 +17,15 @@ limitations under the License. package machine import ( + "crypto" "fmt" "io/ioutil" "os" "runtime" "testing" + "github.com/google/go-cmp/cmp" + "github.com/jimmidyson/go-download" "k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/bootstrapper" "k8s.io/minikube/pkg/minikube/command" @@ -215,3 +218,57 @@ func TestCacheBinary(t *testing.T) { }) } } + +func TestDownloadOptions(t *testing.T) { + var tc = []struct { + url string + version string + want download.FileOptions + }{ + { + url: "https://s/kubernetes-release/release/v1.16.0/bin/amd64/kubectl", + version: "v1.16.0", + want: download.FileOptions{ + download.Options{ + Checksum: "https://s/kubernetes-release/release/v1.16.0/bin/amd64/kubectl.sha1", + ChecksumHash: crypto.SHA1, + }, + download.MkdirAll, + }, + }, + { + url: "https://s/kubernetes-release/release/v1.10.0/bin/hp9k/kubeadm", + version: "v1.10.0", + want: download.FileOptions{ + download.Options{ + Checksum: "https://s/kubernetes-release/release/v1.10.0/bin/hp9k/kubeadm.sha1", + ChecksumHash: crypto.SHA1, + }, + download.MkdirAll, + }, + }, + { + url: "https://s/kubernetes-release/release/v1.18.0/bin/arm64/kubelet", + version: "v1.18.0", + want: download.FileOptions{ + download.Options{ + Checksum: "https://s/kubernetes-release/release/v1.18.0/bin/arm64/kubelet.sha256", + ChecksumHash: crypto.SHA256, + }, + download.MkdirAll, + }, + }, + } + for _, test := range tc { + t.Run(test.version, func(t *testing.T) { + got, err := downloadOptions(test.url, test.version) + if err != nil { + t.Fatalf("unexpected error %v", err) + } + + if diff := cmp.Diff(test.want, got); diff != "" { + t.Errorf("unexpected options(-want +got):\n%s", diff) + } + }) + } +}