Implement minikube image load command

pull/10366/head
Priya Wadhwa 2021-02-02 15:47:07 -08:00
parent 0509fd8413
commit 0a0f39a112
4 changed files with 147 additions and 0 deletions

55
cmd/minikube/cmd/image.go Normal file
View File

@ -0,0 +1,55 @@
/*
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 (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/reason"
)
// imageCmd represents the image command
var imageCmd = &cobra.Command{
Use: "image",
Short: "Load a local image into minikube",
Long: "Load a local image into minikube",
}
// loadImageCmd represents the image load command
var loadImageCmd = &cobra.Command{
Use: "load",
Short: "Load a local image into minikube",
Long: "Load a local image into minikube",
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
exit.Message(reason.Usage, "Please provide an image in your local daemon or a path to an image tarball to load into minikube via <minikube image load IMAGE_NAME>")
}
// Cache and load images into docker daemon
profile := viper.GetString(config.ProfileName)
img := args[0]
if err := machine.LoadImage(profile, img); err != nil {
exit.Error(reason.InternalCacheLoad, "Failed to cache and load images", err)
}
},
}
func init() {
imageCmd.AddCommand(loadImageCmd)
}

View File

@ -201,6 +201,7 @@ func init() {
dockerEnvCmd, dockerEnvCmd,
podmanEnvCmd, podmanEnvCmd,
cacheCmd, cacheCmd,
imageCmd,
}, },
}, },
{ {

View File

@ -123,6 +123,27 @@ func LoadFromTarball(binary, img string) error {
} }
// SaveToTarball saves img as a tarball at the given path
func SaveToTarball(img, path string) error {
if !ExistsImageInDaemon(img) {
return fmt.Errorf("%s does not exist in local daemon, can't save to tarball", img)
}
ref, err := name.ParseReference(img)
if err != nil {
return errors.Wrap(err, "parsing reference")
}
i, err := daemon.Image(ref)
if err != nil {
return errors.Wrap(err, "getting image")
}
f, err := os.Create(path)
if err != nil {
return errors.Wrap(err, "creating tmp path")
}
defer f.Close()
return tarball.Write(ref, i, f)
}
// Tag returns just the image with the tag // Tag returns just the image with the tag
// eg image:tag@sha256:digest -> image:tag if there is an associated tag // eg image:tag@sha256:digest -> image:tag if there is an associated tag
// if not possible, just return the initial img // if not possible, just return the initial img

View File

@ -18,7 +18,9 @@ package machine
import ( import (
"fmt" "fmt"
"io/ioutil"
"os" "os"
"os/exec"
"path" "path"
"path/filepath" "path/filepath"
"strings" "strings"
@ -61,6 +63,74 @@ func CacheImagesForBootstrapper(imageRepository string, version string, clusterB
return nil return nil
} }
// LoadImage loads the local image into the container runtime
func LoadImage(profile, img string) error {
cc, err := config.Load(profile)
if err != nil {
return errors.Wrap(err, "loading profile")
}
// if the image exists in the local daemon, save it as a tarball
if image.ExistsImageInDaemon(img) {
tmpFile, err := ioutil.TempFile("", "")
if err != nil {
return errors.Wrap(err, "temp file")
}
tmpFile.Close()
defer os.Remove(tmpFile.Name())
img = tmpFile.Name()
}
dst := "/tmp/img.tar"
if err := copyAndLoadTarballIntoHost(cc, img, dst, profile); err != nil {
return errors.Wrap(err, "copying tarball into host")
}
return nil
}
func copyAndLoadTarballIntoHost(cc *config.ClusterConfig, srcPath, dstPath, profile string) error {
c, err := config.Load(profile)
if err != nil {
return errors.Wrap(err, "loading profile config")
}
api, err := NewAPIClient()
if err != nil {
return errors.Wrap(err, "api")
}
defer api.Close()
for _, n := range c.Nodes {
m := config.MachineName(*c, n)
h, err := api.Load(m)
if err != nil {
return errors.Wrap(err, "loading api")
}
cr, err := CommandRunner(h)
if err != nil {
return errors.Wrap(err, "command runner")
}
tarballImg, err := assets.NewFileAsset(srcPath, filepath.Dir(dstPath), filepath.Base(dstPath), "0644")
if err != nil {
return errors.Wrap(err, "new file asset")
}
// copy tarball into minikube
if err := cr.Copy(tarballImg); err != nil {
return errors.Wrap(err, "copying tarball")
}
// load image into container runtime
containerRuntime, err := cruntime.New(cruntime.Config{Type: cc.KubernetesConfig.ContainerRuntime, Runner: cr})
if err != nil {
return errors.Wrap(err, "runtime")
}
if err := containerRuntime.LoadImage(dstPath); err != nil {
return errors.Wrap(err, "loading image into container runtime")
}
// delete destination image tarball on host
if _, err := cr.RunCmd(exec.Command("rm", dstPath)); err != nil {
return errors.Wrap(err, "removing destination tarball")
}
}
return nil
}
// LoadImages loads previously cached images into the container runtime // LoadImages loads previously cached images into the container runtime
func LoadImages(cc *config.ClusterConfig, runner command.Runner, images []string, cacheDir string) error { func LoadImages(cc *config.ClusterConfig, runner command.Runner, images []string, cacheDir string) error {
cr, err := cruntime.New(cruntime.Config{Type: cc.KubernetesConfig.ContainerRuntime, Runner: runner}) cr, err := cruntime.New(cruntime.Config{Type: cc.KubernetesConfig.ContainerRuntime, Runner: runner})