Merge pull request #2203 from priyawadhwa/cache-images
Add cache command to cache non-minikube imagespull/2233/head
commit
43e4b0c655
|
@ -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)
|
||||
}
|
|
@ -36,6 +36,7 @@ type setFn func(string, string) error
|
|||
type Setting struct {
|
||||
name string
|
||||
set func(config.MinikubeConfig, string, string) error
|
||||
setMap func(config.MinikubeConfig, string, map[string]interface{}) error
|
||||
validations []setFn
|
||||
callbacks []setFn
|
||||
}
|
||||
|
@ -193,6 +194,11 @@ var settings = []Setting{
|
|||
name: "disable-driver-mounts",
|
||||
set: SetBool,
|
||||
},
|
||||
{
|
||||
name: "cache",
|
||||
set: SetConfigMap,
|
||||
setMap: SetMap,
|
||||
},
|
||||
}
|
||||
|
||||
var ConfigCmd = &cobra.Command{
|
||||
|
@ -213,6 +219,58 @@ func configurableFields() string {
|
|||
return strings.Join(fields, "\n")
|
||||
}
|
||||
|
||||
// AddToConfigMap adds entries to a map in the config file
|
||||
func AddToConfigMap(name string, images []string) error {
|
||||
s, err := findSetting(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Set the values
|
||||
configFile, err := config.ReadConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newImages := make(map[string]interface{})
|
||||
for _, image := range images {
|
||||
newImages[image] = nil
|
||||
}
|
||||
if values, ok := configFile[name].(map[string]interface{}); ok {
|
||||
for key := range values {
|
||||
newImages[key] = nil
|
||||
}
|
||||
}
|
||||
if err = s.setMap(configFile, name, newImages); err != nil {
|
||||
return err
|
||||
}
|
||||
// Write the values
|
||||
return WriteConfig(configFile)
|
||||
}
|
||||
|
||||
// DeleteFromConfigMap deletes entries from a map in the config file
|
||||
func DeleteFromConfigMap(name string, images []string) error {
|
||||
s, err := findSetting(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Set the values
|
||||
configFile, err := config.ReadConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
values, ok := configFile[name]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
for _, image := range images {
|
||||
delete(values.(map[string]interface{}), image)
|
||||
}
|
||||
if err = s.setMap(configFile, name, values.(map[string]interface{})); err != nil {
|
||||
return err
|
||||
}
|
||||
// Write the values
|
||||
return WriteConfig(configFile)
|
||||
}
|
||||
|
||||
// WriteConfig writes a minikube config to the JSON file
|
||||
func WriteConfig(m config.MinikubeConfig) error {
|
||||
f, err := os.Create(constants.ConfigFile)
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
|
@ -60,6 +61,21 @@ func SetString(m config.MinikubeConfig, name string, val string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func SetMap(m config.MinikubeConfig, name string, val map[string]interface{}) error {
|
||||
m[name] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetConfigMap(m config.MinikubeConfig, name string, val string) error {
|
||||
list := strings.Split(val, ",")
|
||||
v := make(map[string]interface{})
|
||||
for _, s := range list {
|
||||
v[s] = nil
|
||||
}
|
||||
m[name] = v
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetInt(m config.MinikubeConfig, name string, val string) error {
|
||||
i, err := strconv.Atoi(val)
|
||||
if err != nil {
|
||||
|
|
|
@ -332,6 +332,12 @@ This can also be done automatically by setting the env var CHANGE_MINIKUBE_NONE_
|
|||
cmdutil.MaybeReportErrorAndExit(err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("Loading cached images from config file.")
|
||||
err = LoadCachedImagesInConfigFile()
|
||||
if err != nil {
|
||||
fmt.Println("Unable to load cached images from config file.")
|
||||
}
|
||||
}
|
||||
|
||||
func validateK8sVersion(version string) {
|
||||
|
|
|
@ -66,6 +66,9 @@ const DefaultMachineName = "minikube"
|
|||
// The name of the default storage class provisioner
|
||||
const DefaultStorageClassProvisioner = "standard"
|
||||
|
||||
// Used to modify the cache field in the config file
|
||||
const Cache = "cache"
|
||||
|
||||
// MakeMiniPath is a utility to calculate a relative path to our directory.
|
||||
func MakeMiniPath(fileName ...string) string {
|
||||
args := []string{GetMinipath()}
|
||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package machine
|
||||
|
||||
import (
|
||||
"golang.org/x/sync/errgroup"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
@ -24,11 +25,11 @@ 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"
|
||||
"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,7 +212,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")
|
||||
}
|
||||
|
||||
|
@ -193,6 +220,43 @@ func LoadFromCacheBlocking(cmd bootstrapper.CommandRunner, src string) error {
|
|||
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 {
|
||||
|
|
Loading…
Reference in New Issue