Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add code for downloading kicbase image to cache #10918

Merged
merged 4 commits into from
Apr 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion cmd/minikube/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ var dirs = [...]string{
localpath.MakeMiniPath("certs"),
localpath.MakeMiniPath("machines"),
localpath.MakeMiniPath("cache"),
localpath.MakeMiniPath("cache", "iso"),
localpath.MakeMiniPath("config"),
localpath.MakeMiniPath("addons"),
localpath.MakeMiniPath("files"),
Expand Down
7 changes: 6 additions & 1 deletion pkg/minikube/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,12 @@ var (
// KubernetesReleaseBinaries are Kubernetes release binaries required for
// kubeadm (kubelet, kubeadm) and the addon manager (kubectl)
KubernetesReleaseBinaries = []string{"kubelet", "kubeadm", "kubectl"}
// ImageCacheDir is the path to the image cache directory

// ISOCacheDir is the path to the virtual machine image cache directory
ISOCacheDir = localpath.MakeMiniPath("cache", "iso")
// KICCacheDir is the path to the container node image cache directory
KICCacheDir = localpath.MakeMiniPath("cache", "kic")
// ImageCacheDir is the path to the container image cache directory
ImageCacheDir = localpath.MakeMiniPath("cache", "images")

// DefaultNamespaces are Kubernetes namespaces used by minikube, including addons
Expand Down
7 changes: 5 additions & 2 deletions pkg/minikube/download/iso.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
"github.com/juju/mutex"
"github.com/pkg/errors"
"k8s.io/klog/v2"
"k8s.io/minikube/pkg/minikube/localpath"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/out"
"k8s.io/minikube/pkg/minikube/style"
"k8s.io/minikube/pkg/util/lock"
Expand Down Expand Up @@ -75,7 +75,7 @@ func localISOPath(u *url.URL) string {
return u.String()
}

return filepath.Join(localpath.MiniPath(), "cache", "iso", path.Base(u.Path))
return filepath.Join(constants.ISOCacheDir, path.Base(u.Path))
}

// ISO downloads and returns the path to the downloaded ISO
Expand Down Expand Up @@ -115,6 +115,9 @@ func downloadISO(isoURL string, skipChecksum bool) error {

// Lock before we check for existence to avoid thundering herd issues
dst := localISOPath(u)
if err := os.MkdirAll(filepath.Dir(dst), 0777); err != nil {
return errors.Wrapf(err, "making cache image directory: %s", dst)
}
spec := lock.PathMutexSpec(dst)
spec.Timeout = 10 * time.Minute
klog.Infof("acquiring lock: %+v", spec)
Expand Down
83 changes: 83 additions & 0 deletions pkg/minikube/image/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
"strings"
Expand Down Expand Up @@ -106,6 +107,23 @@ func DigestByGoLib(imgName string) string {
return cf.Hex
}

// ExistsImageInCache if img exist in local cache directory
func ExistsImageInCache(img string) bool {
f := filepath.Join(constants.KICCacheDir, path.Base(img)+".tar")
f = localpath.SanitizeCacheDir(f)

// Check if image exists locally
klog.Infof("Checking for %s in local cache directory", img)
if st, err := os.Stat(f); err == nil {
if st.Size() > 0 {
klog.Infof("Found %s in local cache directory, skipping pull", img)
return true
}
}
// Else, pull it
return false
}

// ExistsImageInDaemon if img exist in local docker daemon
func ExistsImageInDaemon(img string) bool {
// Check if image exists locally
Expand Down Expand Up @@ -159,6 +177,71 @@ func Tag(img string) string {
return img
}

// WriteImageToCache write img to the local cache directory
func WriteImageToCache(img string) error {
f := filepath.Join(constants.KICCacheDir, path.Base(img)+".tar")
f = localpath.SanitizeCacheDir(f)

if err := os.MkdirAll(filepath.Dir(f), 0777); err != nil {
return errors.Wrapf(err, "making cache image directory: %s", f)
}

// buffered channel
c := make(chan v1.Update, 200)

klog.Infof("Writing %s to local cache", img)
ref, err := name.ParseReference(img)
if err != nil {
return errors.Wrap(err, "parsing reference")
}
klog.V(3).Infof("Getting image %v", ref)
i, err := remote.Image(ref)
if err != nil {
if strings.Contains(err.Error(), "GitHub Docker Registry needs login") {
ErrGithubNeedsLogin = errors.New(err.Error())
return ErrGithubNeedsLogin
} else if strings.Contains(err.Error(), "UNAUTHORIZED") {
ErrNeedsLogin = errors.New(err.Error())
return ErrNeedsLogin
}

return errors.Wrap(err, "getting remote image")
}
klog.V(3).Infof("Writing image %v", ref)
errchan := make(chan error)
p := pb.Full.Start64(0)
fn := strings.Split(ref.Name(), "@")[0]
// abbreviate filename for progress
maxwidth := 30 - len("...")
if len(fn) > maxwidth {
fn = fn[0:maxwidth] + "..."
}
p.Set("prefix", " > "+fn+": ")
p.Set(pb.Bytes, true)

// Just a hair less than 80 (standard terminal width) for aesthetics & pasting into docs
p.SetWidth(79)

go func() {
err = tarball.WriteToFile(f, ref, i, tarball.WithProgress(c))
errchan <- err
}()
var update v1.Update
for {
select {
case update = <-c:
p.SetCurrent(update.Complete)
p.SetTotal(update.Total)
case err = <-errchan:
p.Finish()
if err != nil {
return errors.Wrap(err, "writing tarball image")
}
return nil
}
}
}

// WriteImageToDaemon write img to the local docker daemon
func WriteImageToDaemon(img string) error {
// buffered channel
Expand Down
49 changes: 29 additions & 20 deletions pkg/minikube/node/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,6 @@ func doCacheBinaries(k8sVersion string) error {

// beginDownloadKicBaseImage downloads the kic image
func beginDownloadKicBaseImage(g *errgroup.Group, cc *config.ClusterConfig, downloadOnly bool) {
if cc.Driver != "docker" {
// TODO: driver == "podman"
klog.Info("Driver isn't docker, skipping base image download")
return
}
if image.ExistsImageInDaemon(cc.KicBaseImage) {
klog.Infof("%s exists in daemon, skipping pull", cc.KicBaseImage)
return
}

klog.Infof("Beginning downloading kic base image for %s with %s", cc.Driver, cc.KubernetesConfig.ContainerRuntime)
register.Reg.SetStep(register.PullingBaseImage)
Expand All @@ -135,23 +126,41 @@ func beginDownloadKicBaseImage(g *errgroup.Group, cc *config.ClusterConfig, down
}
}()
for _, img := range append([]string{baseImg}, kic.FallbackImages...) {
if err := image.LoadFromTarball(driver.Docker, img); err == nil {
var err error
if image.ExistsImageInCache(img) {
klog.Infof("%s exists in cache, skipping pull", img)
finalImg = img
} else {
klog.Infof("Downloading %s to local cache", img)
err = image.WriteImageToCache(img)
if err == nil {
klog.Infof("successfully saved %s as a tarball", img)
finalImg = img
}
}
if downloadOnly {
return err
}

if err := image.LoadFromTarball(cc.Driver, img); err == nil {
klog.Infof("successfully loaded %s from cached tarball", img)
// strip the digest from the img before saving it in the config
// because loading an image from tarball to daemon doesn't load the digest
finalImg = img
return nil
}
klog.Infof("Downloading %s to local daemon", img)
err := image.WriteImageToDaemon(img)
if err == nil {
klog.Infof("successfully downloaded %s", img)
finalImg = img
return nil
}
if downloadOnly {
if err := image.SaveToDir([]string{img}, constants.ImageCacheDir); err == nil {
klog.Infof("successfully saved %s as a tarball", img)

if driver.IsDocker(cc.Driver) {
if image.ExistsImageInDaemon(img) {
klog.Infof("%s exists in daemon, skipping pull", img)
finalImg = img
return nil
}

klog.Infof("Downloading %s to local daemon", img)
err = image.WriteImageToDaemon(img)
if err == nil {
klog.Infof("successfully downloaded %s", img)
finalImg = img
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/minikube/tests/dir_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func MakeTempDir() string {
if err != nil {
log.Fatal(err)
}
err = os.MkdirAll(filepath.Join(tempDir, "cache", "iso"), 0777)
err = os.MkdirAll(filepath.Join(tempDir, "cache"), 0777)
if err != nil {
log.Fatal(err)
}
Expand Down