未验证 提交 51ec098b 编写于 作者: P priyawadhwa 提交者: GitHub

Merge pull request #10366 from priyawadhwa/mk-image-load

Implement minikube image load command
......@@ -18,17 +18,25 @@ package cmd
import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"k8s.io/klog/v2"
cmdConfig "k8s.io/minikube/cmd/minikube/cmd/config"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/image"
"k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/node"
"k8s.io/minikube/pkg/minikube/out"
"k8s.io/minikube/pkg/minikube/reason"
)
// cacheImageConfigKey is the config field name used to store which images we have previously cached
const cacheImageConfigKey = "cache"
var (
all string
)
// cacheCmd represents the cache command
var cacheCmd = &cobra.Command{
Use: "cache",
......@@ -42,8 +50,9 @@ var addCacheCmd = &cobra.Command{
Short: "Add an image to local cache.",
Long: "Add an image to local cache.",
Run: func(cmd *cobra.Command, args []string) {
out.WarningT("\"minikube cache\" will be deprecated in upcoming versions, please switch to \"minikube image load\"")
// Cache and load images into docker daemon
if err := machine.CacheAndLoadImages(args); err != nil {
if err := machine.CacheAndLoadImages(args, cacheAddProfiles()); err != nil {
exit.Error(reason.InternalCacheLoad, "Failed to cache and load images", err)
}
// Add images to config file
......@@ -53,6 +62,26 @@ var addCacheCmd = &cobra.Command{
},
}
func addCacheCmdFlags() {
addCacheCmd.Flags().Bool(all, false, "Add image to cache for all running minikube clusters")
}
func cacheAddProfiles() []*config.Profile {
if viper.GetBool(all) {
validProfiles, _, err := config.ListProfiles() // need to load image to all profiles
if err != nil {
klog.Warningf("error listing profiles: %v", err)
}
return validProfiles
}
profile := viper.GetString(config.ProfileName)
p, err := config.LoadProfile(profile)
if err != nil {
exit.Message(reason.Usage, "{{.profile}} profile is not valid: {{.err}}", out.V{"profile": profile, "err": err})
}
return []*config.Profile{p}
}
// deleteCacheCmd represents the cache delete command
var deleteCacheCmd = &cobra.Command{
Use: "delete",
......@@ -76,7 +105,7 @@ var reloadCacheCmd = &cobra.Command{
Short: "reload cached images.",
Long: "reloads images previously added using the 'cache add' subcommand",
Run: func(cmd *cobra.Command, args []string) {
err := node.CacheAndLoadImagesInConfig()
err := node.CacheAndLoadImagesInConfig(cacheAddProfiles())
if err != nil {
exit.Error(reason.GuestCacheLoad, "Failed to reload cached images", err)
}
......@@ -84,6 +113,7 @@ var reloadCacheCmd = &cobra.Command{
}
func init() {
addCacheCmdFlags()
cacheCmd.AddCommand(addCacheCmd)
cacheCmd.AddCommand(deleteCacheCmd)
cacheCmd.AddCommand(reloadCacheCmd)
......
/*
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 to load into minikube via <minikube image load IMAGE_NAME>")
}
// Cache and load images into docker daemon
profile, err := config.LoadProfile(viper.GetString(config.ProfileName))
if err != nil {
exit.Error(reason.Usage, "loading profile", err)
}
img := args[0]
if err := machine.CacheAndLoadImages([]string{img}, []*config.Profile{profile}); err != nil {
exit.Error(reason.GuestImageLoad, "Failed to load image", err)
}
},
}
func init() {
imageCmd.AddCommand(loadImageCmd)
}
......@@ -217,6 +217,7 @@ func init() {
dockerEnvCmd,
podmanEnvCmd,
cacheCmd,
imageCmd,
},
},
{
......
......@@ -158,7 +158,7 @@ func needsTransfer(imgClient *client.Client, imgName string, cr cruntime.Manager
}
// CacheAndLoadImages caches and loads images to all profiles
func CacheAndLoadImages(images []string) error {
func CacheAndLoadImages(images []string, profiles []*config.Profile) error {
if len(images) == 0 {
return nil
}
......@@ -173,10 +173,6 @@ func CacheAndLoadImages(images []string) error {
return errors.Wrap(err, "api")
}
defer api.Close()
profiles, _, err := config.ListProfiles() // need to load image to all profiles
if err != nil {
return errors.Wrap(err, "list profiles")
}
succeeded := []string{}
failed := []string{}
......
......@@ -210,7 +210,7 @@ func saveImagesToTarFromConfig() error {
// CacheAndLoadImagesInConfig loads the images currently in the config file
// called by 'start' and 'cache reload' commands.
func CacheAndLoadImagesInConfig() error {
func CacheAndLoadImagesInConfig(profiles []*config.Profile) error {
images, err := imagesInConfigFile()
if err != nil {
return errors.Wrap(err, "images")
......@@ -218,7 +218,7 @@ func CacheAndLoadImagesInConfig() error {
if len(images) == 0 {
return nil
}
return machine.CacheAndLoadImages(images)
return machine.CacheAndLoadImages(images, profiles)
}
func imagesInConfigFile() ([]string, error) {
......
......@@ -145,10 +145,14 @@ func Start(starter Starter, apiServer bool) (*kubeconfig.Settings, error) {
wg.Add(1)
go func() {
if err := CacheAndLoadImagesInConfig(); err != nil {
defer wg.Done()
profile, err := config.LoadProfile(starter.Cfg.Name)
if err != nil {
out.FailureT("Unable to load profile: {{.error}}", out.V{"error": err})
}
if err := CacheAndLoadImagesInConfig([]*config.Profile{profile}); err != nil {
out.FailureT("Unable to push cached images: {{.error}}", out.V{"error": err})
}
wg.Done()
}()
// enable addons, both old and new!
......
......@@ -240,6 +240,7 @@ var (
GuestCert = Kind{ID: "GUEST_CERT", ExitCode: ExGuestError}
GuestCpConfig = Kind{ID: "GUEST_CP_CONFIG", ExitCode: ExGuestConfig}
GuestDeletion = Kind{ID: "GUEST_DELETION", ExitCode: ExGuestError}
GuestImageLoad = Kind{ID: "GUEST_IMAGE_LOAD", ExitCode: ExGuestError}
GuestLoadHost = Kind{ID: "GUEST_LOAD_HOST", ExitCode: ExGuestError}
GuestMount = Kind{ID: "GUEST_MOUNT", ExitCode: ExGuestError}
GuestMountConflict = Kind{ID: "GUEST_MOUNT_CONFLICT", ExitCode: ExGuestConflict}
......
......@@ -47,6 +47,12 @@ Add an image to local cache.
minikube cache add [flags]
```
### Options
```
-- Add image to cache for all running minikube clusters
```
### Options inherited from parent commands
```
......
---
title: "image"
description: >
Load a local image into minikube
---
## minikube image
Load a local image into minikube
### Synopsis
Load a local image into minikube
### Options inherited from parent commands
```
--add_dir_header If true, adds the file directory to the header of the log messages
--alsologtostderr log to standard error as well as files
-b, --bootstrapper string The name of the cluster bootstrapper that will set up the Kubernetes cluster. (default "kubeadm")
-h, --help
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
--log_dir string If non-empty, write log files in this directory
--log_file string If non-empty, use this log file
--log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
--logtostderr log to standard error instead of files
--one_output If true, only write logs to their native severity level (vs also writing to each lower severity level
-p, --profile string The name of the minikube VM being used. This can be set to allow having multiple instances of minikube independently. (default "minikube")
--skip_headers If true, avoid header prefixes in the log messages
--skip_log_headers If true, avoid headers when opening log files
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
--user string Specifies the user executing the operation. Useful for auditing operations executed by 3rd party tools. Defaults to the operating system username.
-v, --v Level number for the log level verbosity
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
```
## minikube image help
Help about any command
### Synopsis
Help provides help for any command in the application.
Simply type image help [path to command] for full details.
```shell
minikube image help [command] [flags]
```
### Options inherited from parent commands
```
--add_dir_header If true, adds the file directory to the header of the log messages
--alsologtostderr log to standard error as well as files
-b, --bootstrapper string The name of the cluster bootstrapper that will set up the Kubernetes cluster. (default "kubeadm")
-h, --help
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
--log_dir string If non-empty, write log files in this directory
--log_file string If non-empty, use this log file
--log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
--logtostderr log to standard error instead of files
--one_output If true, only write logs to their native severity level (vs also writing to each lower severity level
-p, --profile string The name of the minikube VM being used. This can be set to allow having multiple instances of minikube independently. (default "minikube")
--skip_headers If true, avoid header prefixes in the log messages
--skip_log_headers If true, avoid headers when opening log files
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
--user string Specifies the user executing the operation. Useful for auditing operations executed by 3rd party tools. Defaults to the operating system username.
-v, --v Level number for the log level verbosity
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
```
## minikube image load
Load a local image into minikube
### Synopsis
Load a local image into minikube
```shell
minikube image load [flags]
```
### Options inherited from parent commands
```
--add_dir_header If true, adds the file directory to the header of the log messages
--alsologtostderr log to standard error as well as files
-b, --bootstrapper string The name of the cluster bootstrapper that will set up the Kubernetes cluster. (default "kubeadm")
-h, --help
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
--log_dir string If non-empty, write log files in this directory
--log_file string If non-empty, use this log file
--log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
--logtostderr log to standard error instead of files
--one_output If true, only write logs to their native severity level (vs also writing to each lower severity level
-p, --profile string The name of the minikube VM being used. This can be set to allow having multiple instances of minikube independently. (default "minikube")
--skip_headers If true, avoid header prefixes in the log messages
--skip_log_headers If true, avoid headers when opening log files
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
--user string Specifies the user executing the operation. Useful for auditing operations executed by 3rd party tools. Defaults to the operating system username.
-v, --v Level number for the log level verbosity
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
```
......@@ -127,6 +127,7 @@ func TestFunctional(t *testing.T) {
{"UpdateContextCmd", validateUpdateContextCmd},
{"DockerEnv", validateDockerEnv},
{"NodeLabels", validateNodeLabels},
{"LoadImage", validateLoadImage},
}
for _, tc := range tests {
tc := tc
......@@ -158,6 +159,48 @@ func validateNodeLabels(ctx context.Context, t *testing.T, profile string) {
}
}
// validateLoadImage makes sure that `minikube load image` works as expected
func validateLoadImage(ctx context.Context, t *testing.T, profile string) {
if NoneDriver() {
t.Skip("load image not available on none driver")
}
defer PostMortemLogs(t, profile)
// pull busybox
busybox := "busybox:latest"
rr, err := Run(t, exec.CommandContext(ctx, "docker", "pull", busybox))
if err != nil {
t.Fatalf("starting minikube: %v\n%s", err, rr.Output())
}
// tag busybox
newImage := fmt.Sprintf("busybox:%s", profile)
rr, err = Run(t, exec.CommandContext(ctx, "docker", "tag", busybox, newImage))
if err != nil {
t.Fatalf("starting minikube: %v\n%s", err, rr.Output())
}
// try to load the new image into minikube
rr, err = Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "image", "load", newImage))
if err != nil {
t.Fatalf("loading image into minikube: %v\n%s", err, rr.Output())
}
// make sure the image was correctly loaded
var cmd *exec.Cmd
if ContainerRuntime() == "docker" {
cmd = exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "--", "docker", "images", "--format", "{{.Repository}}:{{.Tag}}")
} else {
cmd = exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "--", "sudo", "ctr", "-n=k8s.io", "image", "ls")
}
rr, err = Run(t, cmd)
if err != nil {
t.Fatalf("listing images: %v\n%s", err, rr.Output())
}
if !strings.Contains(rr.Output(), newImage) {
t.Fatalf("expected %s to be loaded into minikube but the image is not there", newImage)
}
}
// check functionality of minikube after evaling docker-env
// TODO: Add validatePodmanEnv for crio runtime: #10231
func validateDockerEnv(ctx context.Context, t *testing.T, profile string) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册