Add checksum verification
parent
86df9ffb2c
commit
c99bf76ee4
3
Makefile
3
Makefile
|
@ -21,6 +21,7 @@ VERSION ?= v$(RAW_VERSION)
|
||||||
|
|
||||||
KUBERNETES_VERSION ?= $(shell egrep "DefaultKubernetesVersion =" pkg/minikube/constants/constants.go | cut -d \" -f2)
|
KUBERNETES_VERSION ?= $(shell egrep "DefaultKubernetesVersion =" pkg/minikube/constants/constants.go | cut -d \" -f2)
|
||||||
KIC_VERSION ?= $(shell egrep "Version =" pkg/drivers/kic/types.go | cut -d \" -f2)
|
KIC_VERSION ?= $(shell egrep "Version =" pkg/drivers/kic/types.go | cut -d \" -f2)
|
||||||
|
PRELOADED_VOLUMES_GCS_BUCKET ?= $(shell egrep "PreloadedVolumeTarballsBucket =" pkg/minikube/constants/constants.go | cut -d \" -f2)
|
||||||
|
|
||||||
# Default to .0 for higher cache hit rates, as build increments typically don't require new ISO versions
|
# Default to .0 for higher cache hit rates, as build increments typically don't require new ISO versions
|
||||||
ISO_VERSION ?= v$(VERSION_MAJOR).$(VERSION_MINOR).3
|
ISO_VERSION ?= v$(VERSION_MAJOR).$(VERSION_MINOR).3
|
||||||
|
@ -513,7 +514,7 @@ kic-base-image: ## builds the base image used for kic.
|
||||||
|
|
||||||
.PHONY: upload-preloaded-images-tar
|
.PHONY: upload-preloaded-images-tar
|
||||||
upload-preloaded-images-tar: generate-preloaded-images-tar # Upload the preloaded images tar to the GCS bucket. Specify a specific kubernetes version to build via `KUBERNETES_VERSION=vx.y.z make upload-preloaded-images-tar`.
|
upload-preloaded-images-tar: generate-preloaded-images-tar # Upload the preloaded images tar to the GCS bucket. Specify a specific kubernetes version to build via `KUBERNETES_VERSION=vx.y.z make upload-preloaded-images-tar`.
|
||||||
gsutil cp out/preloaded-images-k8s-${KUBERNETES_VERSION}.tar.lz4 gs://minikube-docker-volume-tarballs
|
gsutil cp out/preloaded-images-k8s-${KUBERNETES_VERSION}.tar.lz4 gs://${PRELOADED_VOLUMES_GCS_BUCKET}
|
||||||
|
|
||||||
.PHONY: generate-preloaded-images-tar
|
.PHONY: generate-preloaded-images-tar
|
||||||
generate-preloaded-images-tar: out/minikube
|
generate-preloaded-images-tar: out/minikube
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -3,6 +3,7 @@ module k8s.io/minikube
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
cloud.google.com/go v0.45.1
|
||||||
github.com/Parallels/docker-machine-parallels v1.3.0
|
github.com/Parallels/docker-machine-parallels v1.3.0
|
||||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
|
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
|
||||||
github.com/blang/semver v3.5.0+incompatible
|
github.com/blang/semver v3.5.0+incompatible
|
||||||
|
|
|
@ -30,10 +30,12 @@ import (
|
||||||
"github.com/docker/machine/libmachine/state"
|
"github.com/docker/machine/libmachine/state"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/spf13/viper"
|
||||||
pkgdrivers "k8s.io/minikube/pkg/drivers"
|
pkgdrivers "k8s.io/minikube/pkg/drivers"
|
||||||
"k8s.io/minikube/pkg/drivers/kic/oci"
|
"k8s.io/minikube/pkg/drivers/kic/oci"
|
||||||
"k8s.io/minikube/pkg/minikube/assets"
|
"k8s.io/minikube/pkg/minikube/assets"
|
||||||
"k8s.io/minikube/pkg/minikube/command"
|
"k8s.io/minikube/pkg/minikube/command"
|
||||||
|
"k8s.io/minikube/pkg/minikube/config"
|
||||||
"k8s.io/minikube/pkg/minikube/constants"
|
"k8s.io/minikube/pkg/minikube/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -91,7 +93,7 @@ func (d *Driver) Create() error {
|
||||||
)
|
)
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
glog.Infof("Starting creating preloaded images volume")
|
glog.Infof("Starting creating preloaded images volume")
|
||||||
volumeName, err := oci.CreatePreloadedImagesVolume(d.NodeConfig.KubernetesVersion, BaseImage)
|
volumeName, err := oci.CreatePreloadedImagesVolume(d.NodeConfig.KubernetesVersion, BaseImage, viper.GetString(config.MachineProfile))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Infof("Unable to create preloaded images volume: %v", err)
|
glog.Infof("Unable to create preloaded images volume: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"k8s.io/minikube/pkg/drivers/kic/preload"
|
"k8s.io/minikube/pkg/minikube/preload"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeleteAllVolumesByLabel deletes all volumes that have a specific label
|
// DeleteAllVolumesByLabel deletes all volumes that have a specific label
|
||||||
|
@ -90,18 +90,20 @@ func allVolumesByLabel(ociBin string, label string) ([]string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatePreloadedImagesVolume creates a volume with preloaded images
|
// CreatePreloadedImagesVolume creates a volume with preloaded images
|
||||||
func CreatePreloadedImagesVolume(k8sVersion, baseImage string) (string, error) {
|
// k8sVersion is used to name the volume and baseImage is the image that is run
|
||||||
|
// to extract the preloaded images to the volume
|
||||||
|
func CreatePreloadedImagesVolume(k8sVersion, baseImage, profile string) (string, error) {
|
||||||
if err := PointToHostDockerDaemon(); err != nil {
|
if err := PointToHostDockerDaemon(); err != nil {
|
||||||
return "", errors.Wrap(err, "point host docker-daemon")
|
return "", errors.Wrap(err, "point host docker-daemon")
|
||||||
}
|
}
|
||||||
volumeName := fmt.Sprintf("k8s-%s", k8sVersion)
|
volumeName := fmt.Sprintf("k8s-%s-%s", k8sVersion, profile)
|
||||||
if dockerVolumeExists(volumeName) {
|
if dockerVolumeExists(volumeName) {
|
||||||
return volumeName, nil
|
return volumeName, nil
|
||||||
}
|
}
|
||||||
if err := createDockerVolume(volumeName); err != nil {
|
if err := createDockerVolume(volumeName); err != nil {
|
||||||
return "", errors.Wrap(err, "creating docker volume")
|
return "", errors.Wrap(err, "creating docker volume")
|
||||||
}
|
}
|
||||||
tarballPath := preload.TarballPath(k8sVersion)
|
tarballPath := preload.TarballFilepath(k8sVersion)
|
||||||
|
|
||||||
if err := extractTarballToVolume(tarballPath, volumeName, baseImage); err != nil {
|
if err := extractTarballToVolume(tarballPath, volumeName, baseImage); err != nil {
|
||||||
return "", errors.Wrap(err, "extracting tarball to volume")
|
return "", errors.Wrap(err, "extracting tarball to volume")
|
||||||
|
@ -109,6 +111,7 @@ func CreatePreloadedImagesVolume(k8sVersion, baseImage string) (string, error) {
|
||||||
return volumeName, nil
|
return volumeName, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dockerVolumeExists returns true if a docker volume with the passed in name exists
|
||||||
func dockerVolumeExists(name string) bool {
|
func dockerVolumeExists(name string) bool {
|
||||||
if err := PointToHostDockerDaemon(); err != nil {
|
if err := PointToHostDockerDaemon(); err != nil {
|
||||||
return false
|
return false
|
||||||
|
@ -120,19 +123,20 @@ func dockerVolumeExists(name string) bool {
|
||||||
}
|
}
|
||||||
names := strings.Split(string(out), "\n")
|
names := strings.Split(string(out), "\n")
|
||||||
for _, n := range names {
|
for _, n := range names {
|
||||||
if n == name {
|
if strings.TrimSpace(n) == name {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extractTarballToVolume runs a docker image imageName which extracts the tarball at tarballPath
|
||||||
|
// to the volume named volumeName
|
||||||
func extractTarballToVolume(tarballPath, volumeName, imageName string) error {
|
func extractTarballToVolume(tarballPath, volumeName, imageName string) error {
|
||||||
if err := PointToHostDockerDaemon(); err != nil {
|
if err := PointToHostDockerDaemon(); err != nil {
|
||||||
return errors.Wrap(err, "point host docker-daemon")
|
return errors.Wrap(err, "point host docker-daemon")
|
||||||
}
|
}
|
||||||
cmd := exec.Command(Docker, "run", "--rm", "--entrypoint", "/usr/bin/tar", "-v", fmt.Sprintf("%s:/preloaded.tar:ro", tarballPath), "-v", fmt.Sprintf("%s:/extractDir", volumeName), imageName, "-I", "lz4", "-xvf", "/preloaded.tar", "-C", "/extractDir")
|
cmd := exec.Command(Docker, "run", "--rm", "--entrypoint", "/usr/bin/tar", "-v", fmt.Sprintf("%s:/preloaded.tar:ro", tarballPath), "-v", fmt.Sprintf("%s:/extractDir", volumeName), imageName, "-I", "lz4", "-xvf", "/preloaded.tar", "-C", "/extractDir")
|
||||||
fmt.Println(cmd.Args)
|
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
return errors.Wrapf(err, "output %s", string(out))
|
return errors.Wrapf(err, "output %s", string(out))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2020 The Kubernetes Authors All rights reserved.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package preload
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
|
|
||||||
"github.com/golang/glog"
|
|
||||||
"github.com/jimmidyson/go-download"
|
|
||||||
"k8s.io/minikube/pkg/minikube/localpath"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TarballPath returns the path to the preloaded tarball
|
|
||||||
func TarballPath(k8sVersion string) string {
|
|
||||||
targetDir := localpath.MakeMiniPath("cache", "preloaded-tarball")
|
|
||||||
targetFilepath := path.Join(targetDir, fmt.Sprintf("preloaded-images-k8s-%s.tar.lz4", k8sVersion))
|
|
||||||
return targetFilepath
|
|
||||||
}
|
|
||||||
|
|
||||||
// CacheTarball caches the preloaded images tarball on the host machine
|
|
||||||
func CacheTarball(k8sVersion string) error {
|
|
||||||
targetFilepath := TarballPath(k8sVersion)
|
|
||||||
|
|
||||||
if _, err := os.Stat(targetFilepath); err == nil {
|
|
||||||
glog.Infof("Found %s in cache, skipping downloading", targetFilepath)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
url := fmt.Sprintf("https://storage.googleapis.com/minikube-docker-volume-tarballs/preloaded-images-k8s-%s.tar", k8sVersion)
|
|
||||||
glog.Infof("Downloading %s to %s", url, targetFilepath)
|
|
||||||
return download.ToFile(url, targetFilepath, download.FileOptions{Mkdirs: download.MkdirAll})
|
|
||||||
}
|
|
||||||
|
|
||||||
// UsingPreloadedVolume returns true if the preloaded tarball exists
|
|
||||||
func UsingPreloadedVolume(k8sVersion string) bool {
|
|
||||||
path := TarballPath(k8sVersion)
|
|
||||||
_, err := os.Stat(path)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
|
@ -40,7 +40,6 @@ import (
|
||||||
kconst "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kconst "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
"k8s.io/minikube/pkg/drivers/kic"
|
"k8s.io/minikube/pkg/drivers/kic"
|
||||||
"k8s.io/minikube/pkg/drivers/kic/oci"
|
"k8s.io/minikube/pkg/drivers/kic/oci"
|
||||||
"k8s.io/minikube/pkg/drivers/kic/preload"
|
|
||||||
"k8s.io/minikube/pkg/kapi"
|
"k8s.io/minikube/pkg/kapi"
|
||||||
"k8s.io/minikube/pkg/minikube/bootstrapper"
|
"k8s.io/minikube/pkg/minikube/bootstrapper"
|
||||||
"k8s.io/minikube/pkg/minikube/bootstrapper/bsutil"
|
"k8s.io/minikube/pkg/minikube/bootstrapper/bsutil"
|
||||||
|
@ -53,6 +52,7 @@ import (
|
||||||
"k8s.io/minikube/pkg/minikube/driver"
|
"k8s.io/minikube/pkg/minikube/driver"
|
||||||
"k8s.io/minikube/pkg/minikube/machine"
|
"k8s.io/minikube/pkg/minikube/machine"
|
||||||
"k8s.io/minikube/pkg/minikube/out"
|
"k8s.io/minikube/pkg/minikube/out"
|
||||||
|
"k8s.io/minikube/pkg/minikube/preload"
|
||||||
"k8s.io/minikube/pkg/minikube/vmpath"
|
"k8s.io/minikube/pkg/minikube/vmpath"
|
||||||
"k8s.io/minikube/pkg/util/retry"
|
"k8s.io/minikube/pkg/util/retry"
|
||||||
)
|
)
|
||||||
|
|
|
@ -63,6 +63,9 @@ const (
|
||||||
MinikubeActiveDockerdEnv = "MINIKUBE_ACTIVE_DOCKERD"
|
MinikubeActiveDockerdEnv = "MINIKUBE_ACTIVE_DOCKERD"
|
||||||
// PodmanVarlinkBridgeEnv is used for podman settings
|
// PodmanVarlinkBridgeEnv is used for podman settings
|
||||||
PodmanVarlinkBridgeEnv = "PODMAN_VARLINK_BRIDGE"
|
PodmanVarlinkBridgeEnv = "PODMAN_VARLINK_BRIDGE"
|
||||||
|
|
||||||
|
// PreloadedVolumeTarballsBucket is the name of the GCS bucket where preloaded volume tarballs exist
|
||||||
|
PreloadedVolumeTarballsBucket = "minikube-preloaded-volume-tarballs"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -25,15 +25,14 @@ import (
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config"
|
cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config"
|
||||||
"k8s.io/minikube/pkg/drivers/kic"
|
"k8s.io/minikube/pkg/drivers/kic"
|
||||||
"k8s.io/minikube/pkg/drivers/kic/preload"
|
|
||||||
"k8s.io/minikube/pkg/minikube/config"
|
"k8s.io/minikube/pkg/minikube/config"
|
||||||
"k8s.io/minikube/pkg/minikube/constants"
|
"k8s.io/minikube/pkg/minikube/constants"
|
||||||
"k8s.io/minikube/pkg/minikube/driver"
|
|
||||||
"k8s.io/minikube/pkg/minikube/exit"
|
"k8s.io/minikube/pkg/minikube/exit"
|
||||||
"k8s.io/minikube/pkg/minikube/image"
|
"k8s.io/minikube/pkg/minikube/image"
|
||||||
"k8s.io/minikube/pkg/minikube/localpath"
|
"k8s.io/minikube/pkg/minikube/localpath"
|
||||||
"k8s.io/minikube/pkg/minikube/machine"
|
"k8s.io/minikube/pkg/minikube/machine"
|
||||||
"k8s.io/minikube/pkg/minikube/out"
|
"k8s.io/minikube/pkg/minikube/out"
|
||||||
|
"k8s.io/minikube/pkg/minikube/preload"
|
||||||
)
|
)
|
||||||
|
|
||||||
// beginCacheRequiredImages caches images required for kubernetes version in the background
|
// beginCacheRequiredImages caches images required for kubernetes version in the background
|
||||||
|
@ -47,16 +46,11 @@ func beginCacheRequiredImages(g *errgroup.Group, imageRepository string, k8sVers
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleDownloadOnly(cacheGroup *errgroup.Group, k8sVersion, driverName string) {
|
func handleDownloadOnly(cacheGroup, kicGroup *errgroup.Group, k8sVersion, driverName string) {
|
||||||
// If --download-only, complete the remaining downloads and exit.
|
// If --download-only, complete the remaining downloads and exit.
|
||||||
if !viper.GetBool("download-only") {
|
if !viper.GetBool("download-only") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var kicArtifactsGroup errgroup.Group
|
|
||||||
if driver.IsKIC(driverName) { // for kic we need to find what port docker/podman chose for us
|
|
||||||
// Download kic base image and preloaded images tarball
|
|
||||||
beginDownloadKicArtifacts(&kicArtifactsGroup, k8sVersion)
|
|
||||||
}
|
|
||||||
if err := doCacheBinaries(k8sVersion); err != nil {
|
if err := doCacheBinaries(k8sVersion); err != nil {
|
||||||
exit.WithError("Failed to cache binaries", err)
|
exit.WithError("Failed to cache binaries", err)
|
||||||
}
|
}
|
||||||
|
@ -64,7 +58,7 @@ func handleDownloadOnly(cacheGroup *errgroup.Group, k8sVersion, driverName strin
|
||||||
exit.WithError("Failed to cache kubectl", err)
|
exit.WithError("Failed to cache kubectl", err)
|
||||||
}
|
}
|
||||||
waitCacheRequiredImages(cacheGroup)
|
waitCacheRequiredImages(cacheGroup)
|
||||||
waitDownloadKicArtifacts(&kicArtifactsGroup)
|
waitDownloadKicArtifacts(kicGroup)
|
||||||
if err := saveImagesToTarFromConfig(); err != nil {
|
if err := saveImagesToTarFromConfig(); err != nil {
|
||||||
exit.WithError("Failed to cache images to tar", err)
|
exit.WithError("Failed to cache images to tar", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import (
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
"k8s.io/minikube/pkg/addons"
|
"k8s.io/minikube/pkg/addons"
|
||||||
"k8s.io/minikube/pkg/drivers/kic/preload"
|
|
||||||
"k8s.io/minikube/pkg/minikube/config"
|
"k8s.io/minikube/pkg/minikube/config"
|
||||||
"k8s.io/minikube/pkg/minikube/driver"
|
"k8s.io/minikube/pkg/minikube/driver"
|
||||||
"k8s.io/minikube/pkg/minikube/exit"
|
"k8s.io/minikube/pkg/minikube/exit"
|
||||||
|
@ -38,13 +37,15 @@ func Start(mc config.MachineConfig, n config.Node, primary bool, existingAddons
|
||||||
k8sVersion := mc.KubernetesConfig.KubernetesVersion
|
k8sVersion := mc.KubernetesConfig.KubernetesVersion
|
||||||
driverName := mc.Driver
|
driverName := mc.Driver
|
||||||
|
|
||||||
// Now that the ISO is downloaded, pull images in the background while the VM boots.
|
// See if we can create a volume of preloaded images
|
||||||
var cacheGroup errgroup.Group
|
// If not, pull images in the background while the VM boots.
|
||||||
if !preload.UsingPreloadedVolume(k8sVersion) && driver.IsKIC(driverName) {
|
var kicGroup errgroup.Group
|
||||||
beginCacheRequiredImages(&cacheGroup, mc.KubernetesConfig.ImageRepository, k8sVersion)
|
if driver.IsKIC(driverName) {
|
||||||
} else {
|
beginDownloadKicArtifacts(&kicGroup, k8sVersion)
|
||||||
mc.KubernetesConfig.ShouldLoadCachedImages = false
|
mc.KubernetesConfig.ShouldLoadCachedImages = false
|
||||||
}
|
}
|
||||||
|
var cacheGroup errgroup.Group
|
||||||
|
beginCacheRequiredImages(&cacheGroup, mc.KubernetesConfig.ImageRepository, k8sVersion)
|
||||||
|
|
||||||
// Abstraction leakage alert: startHost requires the config to be saved, to satistfy pkg/provision/buildroot.
|
// Abstraction leakage alert: startHost requires the config to be saved, to satistfy pkg/provision/buildroot.
|
||||||
// Hence, saveConfig must be called before startHost, and again afterwards when we know the IP.
|
// Hence, saveConfig must be called before startHost, and again afterwards when we know the IP.
|
||||||
|
@ -53,13 +54,14 @@ func Start(mc config.MachineConfig, n config.Node, primary bool, existingAddons
|
||||||
}
|
}
|
||||||
|
|
||||||
// exits here in case of --download-only option.
|
// exits here in case of --download-only option.
|
||||||
handleDownloadOnly(&cacheGroup, k8sVersion, driverName)
|
handleDownloadOnly(&cacheGroup, &kicGroup, k8sVersion, driverName)
|
||||||
mRunner, preExists, machineAPI, host := startMachine(&mc, &n)
|
mRunner, preExists, machineAPI, host := startMachine(&mc, &n)
|
||||||
defer machineAPI.Close()
|
defer machineAPI.Close()
|
||||||
// configure the runtime (docker, containerd, crio)
|
// configure the runtime (docker, containerd, crio)
|
||||||
cr := configureRuntimes(mRunner, driverName, mc.KubernetesConfig)
|
cr := configureRuntimes(mRunner, driverName, mc.KubernetesConfig)
|
||||||
showVersionInfo(k8sVersion, cr)
|
showVersionInfo(k8sVersion, cr)
|
||||||
waitCacheRequiredImages(&cacheGroup)
|
waitCacheRequiredImages(&cacheGroup)
|
||||||
|
waitDownloadKicArtifacts(&kicGroup)
|
||||||
|
|
||||||
//TODO(sharifelgamal): Part out the cluster-wide operations, perhaps using the "primary" param
|
//TODO(sharifelgamal): Part out the cluster-wide operations, perhaps using the "primary" param
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package preload
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/md5"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"cloud.google.com/go/storage"
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"github.com/hashicorp/go-getter"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"k8s.io/minikube/pkg/minikube/constants"
|
||||||
|
"k8s.io/minikube/pkg/minikube/localpath"
|
||||||
|
"k8s.io/minikube/pkg/minikube/out"
|
||||||
|
"k8s.io/minikube/pkg/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// returns name of the tarball
|
||||||
|
func tarballName(k8sVersion string) string {
|
||||||
|
return fmt.Sprintf("preloaded-images-k8s-%s.tar.lz4", k8sVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the name of the checksum file
|
||||||
|
func checksumName(k8sVersion string) string {
|
||||||
|
return fmt.Sprintf("preloaded-images-k8s-%s.tar.lz4.checksum", k8sVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns target dir for all cached items related to preloading
|
||||||
|
func targetDir() string {
|
||||||
|
return localpath.MakeMiniPath("cache", "preloaded-tarball")
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns path to checksum file
|
||||||
|
func checksumFilepath(k8sVersion string) string {
|
||||||
|
return path.Join(targetDir(), checksumName(k8sVersion))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TarballFilepath returns the path to the preloaded tarball
|
||||||
|
func TarballFilepath(k8sVersion string) string {
|
||||||
|
return path.Join(targetDir(), tarballName(k8sVersion))
|
||||||
|
}
|
||||||
|
|
||||||
|
// remoteTarballURL returns the URL for the remote tarball in GCS
|
||||||
|
func remoteTarballURL(k8sVersion string) string {
|
||||||
|
return fmt.Sprintf("https://storage.googleapis.com/%s/%s", constants.PreloadedVolumeTarballsBucket, tarballName(k8sVersion))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheTarball caches the preloaded images tarball on the host machine
|
||||||
|
func CacheTarball(k8sVersion string) error {
|
||||||
|
targetFilepath := TarballFilepath(k8sVersion)
|
||||||
|
|
||||||
|
if _, err := os.Stat(targetFilepath); err == nil {
|
||||||
|
if err := verifyChecksum(k8sVersion); err == nil {
|
||||||
|
glog.Infof("Found %s in cache, skipping downloading", targetFilepath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
url := remoteTarballURL(k8sVersion)
|
||||||
|
|
||||||
|
// Make sure we support this k8s version
|
||||||
|
if _, err := http.Get(url); err != nil {
|
||||||
|
glog.Infof("Unable to get response from %s, skipping downloading: %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
out.T(out.FileDownload, "Downloading preloaded images tarball for k8s {{.version}}:", out.V{"version": k8sVersion})
|
||||||
|
os.Remove(targetFilepath)
|
||||||
|
client := &getter.Client{
|
||||||
|
Src: url,
|
||||||
|
Dst: targetFilepath,
|
||||||
|
Mode: getter.ClientModeFile,
|
||||||
|
Options: []getter.ClientOption{getter.WithProgress(util.DefaultProgressBar)},
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.Infof("Downloading: %+v", client)
|
||||||
|
if err := client.Get(); err != nil {
|
||||||
|
return errors.Wrapf(err, "download failed: %s", url)
|
||||||
|
}
|
||||||
|
// Give downloaded drivers a baseline decent file permission
|
||||||
|
if err := os.Chmod(targetFilepath, 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Save checksum file locally
|
||||||
|
if err := saveChecksumFile(k8sVersion); err != nil {
|
||||||
|
return errors.Wrap(err, "saving checksum file")
|
||||||
|
}
|
||||||
|
return verifyChecksum(k8sVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
func saveChecksumFile(k8sVersion string) error {
|
||||||
|
ctx := context.Background()
|
||||||
|
client, err := storage.NewClient(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
attrs, err := client.Bucket(constants.PreloadedVolumeTarballsBucket).Object(tarballName(k8sVersion)).Attrs(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
checksum := attrs.MD5
|
||||||
|
return ioutil.WriteFile(checksumFilepath(k8sVersion), checksum, 0644)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cachedTarballExists(k8sVersion string) bool {
|
||||||
|
_, err := os.Stat(TarballFilepath(k8sVersion))
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// verifyChecksum returns true if the checksum of the local binary matches
|
||||||
|
// the checksum of the remote binary
|
||||||
|
func verifyChecksum(k8sVersion string) error {
|
||||||
|
// get md5 checksum of tarball path
|
||||||
|
contents, err := ioutil.ReadFile(TarballFilepath(k8sVersion))
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "reading tarball")
|
||||||
|
}
|
||||||
|
checksum := md5.Sum(contents)
|
||||||
|
|
||||||
|
remoteChecksum, err := ioutil.ReadFile(checksumFilepath(k8sVersion))
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "reading checksum file")
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a slice of checksum, which is [16]byte
|
||||||
|
if string(remoteChecksum) != string(checksum[:]) {
|
||||||
|
return fmt.Errorf("checksum of %s does not match remote checksum", TarballFilepath(k8sVersion))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UsingPreloadedVolume(k8sVersion string) bool {
|
||||||
|
return true
|
||||||
|
}
|
Loading…
Reference in New Issue