Skip to content

Commit 0d99d18

Browse files
committed
Allow loading local images as well as from cache
Previously only allowed loading from daemon or remote via the cache, and not directly from local tarball.
1 parent ff0e25a commit 0d99d18

File tree

4 files changed

+102
-17
lines changed

4 files changed

+102
-17
lines changed

cmd/minikube/cmd/image.go

+43-5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ limitations under the License.
1717
package cmd
1818

1919
import (
20+
"os"
21+
"strings"
22+
2023
"github.com/spf13/cobra"
2124
"github.com/spf13/viper"
2225
"k8s.io/minikube/pkg/minikube/config"
@@ -32,11 +35,17 @@ var imageCmd = &cobra.Command{
3235
Long: "Load a local image into minikube",
3336
}
3437

38+
var (
39+
imgDaemon bool
40+
imgRemote bool
41+
)
42+
3543
// loadImageCmd represents the image load command
3644
var loadImageCmd = &cobra.Command{
37-
Use: "load",
38-
Short: "Load a local image into minikube",
39-
Long: "Load a local image into minikube",
45+
Use: "load",
46+
Short: "Load a image into minikube",
47+
Long: "Load a image into minikube",
48+
Example: "minikube image load image\nminikube image load image.tar",
4049
Run: func(cmd *cobra.Command, args []string) {
4150
if len(args) == 0 {
4251
exit.Message(reason.Usage, "Please provide an image in your local daemon to load into minikube via <minikube image load IMAGE_NAME>")
@@ -47,12 +56,41 @@ var loadImageCmd = &cobra.Command{
4756
exit.Error(reason.Usage, "loading profile", err)
4857
}
4958
img := args[0]
50-
if err := machine.CacheAndLoadImages([]string{img}, []*config.Profile{profile}); err != nil {
51-
exit.Error(reason.GuestImageLoad, "Failed to load image", err)
59+
60+
var local bool
61+
if imgRemote || imgDaemon {
62+
local = false
63+
} else if strings.HasPrefix(img, "/") || strings.HasPrefix(img, ".") {
64+
local = true
65+
imgDaemon = false
66+
imgRemote = false
67+
} else if _, err := os.Stat(img); err == nil {
68+
local = true
69+
imgDaemon = false
70+
imgRemote = false
71+
} else {
72+
imgDaemon = true
73+
imgRemote = true
74+
}
75+
76+
// Currently "image.retrieveImage" always tries to load both from daemon and from remote
77+
// There is no way to skip daemon.Image or remote.Image, for the vague "ref" string given.
78+
if imgDaemon || imgRemote {
79+
if err := machine.CacheAndLoadImages([]string{img}, []*config.Profile{profile}); err != nil {
80+
exit.Error(reason.GuestImageLoad, "Failed to load image", err)
81+
}
82+
// Load images from local files, without doing any caching or checks in container runtime
83+
// This is similar to tarball.Image but it is done by the container runtime in the cluster.
84+
} else if local {
85+
if err := machine.DoLoadImages([]string{img}, []*config.Profile{profile}, ""); err != nil {
86+
exit.Error(reason.GuestImageLoad, "Failed to load image", err)
87+
}
5288
}
5389
},
5490
}
5591

5692
func init() {
5793
imageCmd.AddCommand(loadImageCmd)
94+
loadImageCmd.Flags().BoolVar(&imgDaemon, "daemon", false, "Cache image from docker daemon")
95+
loadImageCmd.Flags().BoolVar(&imgRemote, "remote", false, "Cache image from remote registry")
5896
}

pkg/minikube/bootstrapper/kubeadm/kubeadm.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -859,7 +859,7 @@ func (k *Bootstrapper) UpdateCluster(cfg config.ClusterConfig) error {
859859
}
860860

861861
if cfg.KubernetesConfig.ShouldLoadCachedImages {
862-
if err := machine.LoadImages(&cfg, k.c, images, constants.ImageCacheDir); err != nil {
862+
if err := machine.LoadCachedImages(&cfg, k.c, images, constants.ImageCacheDir); err != nil {
863863
out.FailureT("Unable to load cached images: {{.error}}", out.V{"error": err})
864864
}
865865
}

pkg/minikube/machine/cache_images.go

+42-9
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ func CacheImagesForBootstrapper(imageRepository string, version string, clusterB
6161
return nil
6262
}
6363

64-
// LoadImages loads previously cached images into the container runtime
65-
func LoadImages(cc *config.ClusterConfig, runner command.Runner, images []string, cacheDir string) error {
64+
// LoadCachedImages loads previously cached images into the container runtime
65+
func LoadCachedImages(cc *config.ClusterConfig, runner command.Runner, images []string, cacheDir string) error {
6666
cr, err := cruntime.New(cruntime.Config{Type: cc.KubernetesConfig.ContainerRuntime, Runner: runner})
6767
if err != nil {
6868
return errors.Wrap(err, "runtime")
@@ -73,6 +73,7 @@ func LoadImages(cc *config.ClusterConfig, runner command.Runner, images []string
7373
klog.Infof("Images are preloaded, skipping loading")
7474
return nil
7575
}
76+
7677
klog.Infof("LoadImages start: %s", images)
7778
start := time.Now()
7879

@@ -102,7 +103,7 @@ func LoadImages(cc *config.ClusterConfig, runner command.Runner, images []string
102103
return nil
103104
}
104105
klog.Infof("%q needs transfer: %v", image, err)
105-
return transferAndLoadImage(runner, cc.KubernetesConfig, image, cacheDir)
106+
return transferAndLoadCachedImage(runner, cc.KubernetesConfig, image, cacheDir)
106107
})
107108
}
108109
if err := g.Wait(); err != nil {
@@ -157,6 +158,22 @@ func needsTransfer(imgClient *client.Client, imgName string, cr cruntime.Manager
157158
return nil
158159
}
159160

161+
// LoadLocalImages loads images into the container runtime
162+
func LoadLocalImages(cc *config.ClusterConfig, runner command.Runner, images []string) error {
163+
var g errgroup.Group
164+
for _, image := range images {
165+
image := image
166+
g.Go(func() error {
167+
return transferAndLoadImage(runner, cc.KubernetesConfig, image)
168+
})
169+
}
170+
if err := g.Wait(); err != nil {
171+
return errors.Wrap(err, "loading images")
172+
}
173+
klog.Infoln("Successfully loaded all images")
174+
return nil
175+
}
176+
160177
// CacheAndLoadImages caches and loads images to all profiles
161178
func CacheAndLoadImages(images []string, profiles []*config.Profile) error {
162179
if len(images) == 0 {
@@ -168,6 +185,11 @@ func CacheAndLoadImages(images []string, profiles []*config.Profile) error {
168185
return errors.Wrap(err, "save to dir")
169186
}
170187

188+
return DoLoadImages(images, profiles, constants.ImageCacheDir)
189+
}
190+
191+
// DoLoadImages loads images to all profiles
192+
func DoLoadImages(images []string, profiles []*config.Profile, cacheDir string) error {
171193
api, err := NewAPIClient()
172194
if err != nil {
173195
return errors.Wrap(err, "api")
@@ -209,7 +231,13 @@ func CacheAndLoadImages(images []string, profiles []*config.Profile) error {
209231
if err != nil {
210232
return err
211233
}
212-
err = LoadImages(c, cr, images, constants.ImageCacheDir)
234+
if cacheDir != "" {
235+
// loading image names, from cache
236+
err = LoadCachedImages(c, cr, images, cacheDir)
237+
} else {
238+
// loading image files
239+
err = LoadLocalImages(c, cr, images)
240+
}
213241
if err != nil {
214242
failed = append(failed, m)
215243
klog.Warningf("Failed to load cached images for profile %s. make sure the profile is running. %v", pName, err)
@@ -226,15 +254,20 @@ func CacheAndLoadImages(images []string, profiles []*config.Profile) error {
226254
return nil
227255
}
228256

229-
// transferAndLoadImage transfers and loads a single image from the cache
230-
func transferAndLoadImage(cr command.Runner, k8s config.KubernetesConfig, imgName string, cacheDir string) error {
257+
// transferAndLoadCachedImage transfers and loads a single image from the cache
258+
func transferAndLoadCachedImage(cr command.Runner, k8s config.KubernetesConfig, imgName string, cacheDir string) error {
259+
src := filepath.Join(cacheDir, imgName)
260+
src = localpath.SanitizeCacheDir(src)
261+
return transferAndLoadImage(cr, k8s, src)
262+
}
263+
264+
// transferAndLoadImage transfers and loads a single image
265+
func transferAndLoadImage(cr command.Runner, k8s config.KubernetesConfig, src string) error {
231266
r, err := cruntime.New(cruntime.Config{Type: k8s.ContainerRuntime, Runner: cr})
232267
if err != nil {
233268
return errors.Wrap(err, "runtime")
234269
}
235-
src := filepath.Join(cacheDir, imgName)
236-
src = localpath.SanitizeCacheDir(src)
237-
klog.Infof("Loading image from cache: %s", src)
270+
klog.Infof("Loading image from: %s", src)
238271
filename := filepath.Base(src)
239272
if _, err := os.Stat(src); err != nil {
240273
return err

site/content/en/docs/commands/image.md

+16-2
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,30 @@ minikube image help [command] [flags]
7272

7373
## minikube image load
7474

75-
Load a local image into minikube
75+
Load a image into minikube
7676

7777
### Synopsis
7878

79-
Load a local image into minikube
79+
Load a image into minikube
8080

8181
```shell
8282
minikube image load [flags]
8383
```
8484

85+
### Examples
86+
87+
```
88+
minikube image load image
89+
minikube image load image.tar
90+
```
91+
92+
### Options
93+
94+
```
95+
--daemon Cache image from docker daemon
96+
--remote Cache image from remote registry
97+
```
98+
8599
### Options inherited from parent commands
86100

87101
```

0 commit comments

Comments
 (0)