-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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 cache command to cache non-minikube images #2203
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
Copyright 2017 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 cmd | ||
|
||
import ( | ||
"fmt" | ||
"github.com/spf13/cobra" | ||
cmdConfig "k8s.io/minikube/cmd/minikube/cmd/config" | ||
"k8s.io/minikube/pkg/minikube/config" | ||
"k8s.io/minikube/pkg/minikube/constants" | ||
"k8s.io/minikube/pkg/minikube/machine" | ||
"os" | ||
) | ||
|
||
// cacheCmd represents the cache command | ||
var cacheCmd = &cobra.Command{ | ||
Use: "cache", | ||
Short: "Add or delete an image from the local cache.", | ||
Long: "Add or delete an image from the local cache.", | ||
} | ||
|
||
// addCacheCmd represents the cache add command | ||
var addCacheCmd = &cobra.Command{ | ||
Use: "add", | ||
Short: "Add an image to local cache.", | ||
Long: "Add an image to local cache.", | ||
Run: func(cmd *cobra.Command, args []string) { | ||
// Cache and load images into docker daemon | ||
if err := machine.CacheAndLoadImages(args); err != nil { | ||
fmt.Fprintf(os.Stderr, "Error caching and loading images: %s\n", err) | ||
os.Exit(1) | ||
} | ||
// Add images to config file | ||
if err := cmdConfig.AddToConfigMap(constants.Cache, args); err != nil { | ||
fmt.Fprintf(os.Stderr, "Error adding cached images to config file: %s\n", err) | ||
os.Exit(1) | ||
} | ||
}, | ||
} | ||
|
||
// deleteCacheCmd represents the cache delete command | ||
var deleteCacheCmd = &cobra.Command{ | ||
Use: "delete", | ||
Short: "Delete an image from the local cache.", | ||
Long: "Delete an image from the local cache.", | ||
Run: func(cmd *cobra.Command, args []string) { | ||
// Delete images from config file | ||
if err := cmdConfig.DeleteFromConfigMap(constants.Cache, args); err != nil { | ||
fmt.Fprintf(os.Stderr, "Error deleting images from config file: %s\n", err) | ||
os.Exit(1) | ||
} | ||
// Delete images from cache/images directory | ||
if err := machine.DeleteFromImageCacheDir(args); err != nil { | ||
fmt.Fprintf(os.Stderr, "Error deleting images: %s\n", err) | ||
os.Exit(1) | ||
} | ||
}, | ||
} | ||
|
||
// LoadCachedImagesInConfigFile loads the images currently in the config file (minikube start) | ||
func LoadCachedImagesInConfigFile() error { | ||
configFile, err := config.ReadConfig() | ||
if err != nil { | ||
return err | ||
} | ||
if values, ok := configFile[constants.Cache]; ok { | ||
var images []string | ||
for key := range values.(map[string]interface{}) { | ||
images = append(images, key) | ||
} | ||
return machine.CacheAndLoadImages(images) | ||
} | ||
return nil | ||
} | ||
|
||
func init() { | ||
cacheCmd.AddCommand(addCacheCmd) | ||
cacheCmd.AddCommand(deleteCacheCmd) | ||
RootCmd.AddCommand(cacheCmd) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,18 +17,19 @@ limitations under the License. | |
package machine | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I supposed this never worked, but we never cared about checking the error since it was done on a best-effort basis. But deleting the temp image tarballs in the VM requires sudo diff --git a/pkg/minikube/machine/cache_images.go b/pkg/minikube/machine/cache_images.go
index ec26c0230..63cf4e40a 100644
--- a/pkg/minikube/machine/cache_images.go
+++ b/pkg/minikube/machine/cache_images.go
@@ -17,7 +17,6 @@ limitations under the License.
package machine
import (
- "golang.org/x/sync/errgroup"
"io/ioutil"
"os"
"os/exec"
@@ -25,6 +24,8 @@ import (
"runtime"
"strings"
+ "golang.org/x/sync/errgroup"
+
"k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/minikube/bootstrapper"
"k8s.io/minikube/pkg/minikube/config"
@@ -212,7 +213,7 @@ func LoadFromCacheBlocking(cmd bootstrapper.CommandRunner, src string) error {
return errors.Wrapf(err, "loading docker image: %s", dst)
}
- if err := cmd.Run("rm -rf " + dst); err != nil {
+ if err := cmd.Run("sudo rm -rf " + dst); err != nil {
return errors.Wrap(err, "deleting temp docker image location")
} |
||
|
||
import ( | ||
"golang.org/x/sync/errgroup" | ||
"io/ioutil" | ||
"os" | ||
"os/exec" | ||
"path/filepath" | ||
"runtime" | ||
"strings" | ||
|
||
"golang.org/x/sync/errgroup" | ||
|
||
"k8s.io/minikube/pkg/minikube/assets" | ||
"k8s.io/minikube/pkg/minikube/bootstrapper" | ||
"k8s.io/minikube/pkg/minikube/config" | ||
"k8s.io/minikube/pkg/minikube/constants" | ||
"k8s.io/minikube/pkg/minikube/sshutil" | ||
|
||
"github.com/containers/image/copy" | ||
"github.com/containers/image/docker" | ||
|
@@ -98,6 +99,32 @@ func LoadImages(cmd bootstrapper.CommandRunner, images []string, cacheDir string | |
return nil | ||
} | ||
|
||
func CacheAndLoadImages(images []string) error { | ||
if err := CacheImages(images, constants.ImageCacheDir); err != nil { | ||
return err | ||
} | ||
api, err := NewAPIClient() | ||
if err != nil { | ||
return err | ||
} | ||
defer api.Close() | ||
h, err := api.Load(config.GetMachineName()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
client, err := sshutil.NewSSHClient(h.Driver) | ||
if err != nil { | ||
return err | ||
} | ||
cmdRunner, err := bootstrapper.NewSSHRunner(client), nil | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return LoadImages(cmdRunner, images, constants.ImageCacheDir) | ||
} | ||
|
||
// # ParseReference cannot have a : in the directory path | ||
func sanitizeCacheDir(image string) string { | ||
if runtime.GOOS == "windows" && hasWindowsDriveLetter(image) { | ||
|
@@ -185,14 +212,51 @@ func LoadFromCacheBlocking(cmd bootstrapper.CommandRunner, src string) error { | |
return errors.Wrapf(err, "loading docker image: %s", dst) | ||
} | ||
|
||
if err := cmd.Run("rm -rf " + dst); err != nil { | ||
if err := cmd.Run("sudo rm -rf " + dst); err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does this need sudo? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because its root owned and the command runner runs as the docker user. |
||
return errors.Wrap(err, "deleting temp docker image location") | ||
} | ||
|
||
glog.Infof("Successfully loaded image %s from cache", src) | ||
return nil | ||
} | ||
|
||
func DeleteFromImageCacheDir(images []string) error { | ||
for _, image := range images { | ||
path := filepath.Join(constants.ImageCacheDir, image) | ||
glog.Infoln("Deleting image in cache at ", path) | ||
if err := os.Remove(path); err != nil { | ||
return err | ||
} | ||
} | ||
return cleanImageCacheDir() | ||
} | ||
|
||
func cleanImageCacheDir() error { | ||
err := filepath.Walk(constants.ImageCacheDir, func(path string, info os.FileInfo, err error) error { | ||
// If error is not nil, it's because the path was already deleted and doesn't exist | ||
// Move on to next path | ||
if err != nil { | ||
return nil | ||
} | ||
// Check if path is directory | ||
if !info.IsDir() { | ||
return nil | ||
} | ||
// If directory is empty, delete it | ||
entries, err := ioutil.ReadDir(path) | ||
if err != nil { | ||
return err | ||
} | ||
if len(entries) == 0 { | ||
if err = os.Remove(path); err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
}) | ||
return err | ||
} | ||
|
||
func getSrcRef(image string) (types.ImageReference, error) { | ||
srcRef, err := docker.ParseReference("//" + image) | ||
if err != nil { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also needs a set method, since thats what
minikube config set
uses. Otherwise, it will panic!