Add ListImages function and image list command
parent
db3fd51194
commit
35d8d4aa52
|
@ -145,9 +145,28 @@ $ minikube image unload image busybox
|
|||
},
|
||||
}
|
||||
|
||||
var listImageCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List images",
|
||||
Example: `
|
||||
$ minikube image list
|
||||
`,
|
||||
Aliases: []string{"ls"},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
profile, err := config.LoadProfile(viper.GetString(config.ProfileName))
|
||||
if err != nil {
|
||||
exit.Error(reason.Usage, "loading profile", err)
|
||||
}
|
||||
if err := machine.ListImages(profile); err != nil {
|
||||
exit.Error(reason.GuestImageList, "Failed to list images", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
imageCmd.AddCommand(loadImageCmd)
|
||||
imageCmd.AddCommand(removeImageCmd)
|
||||
loadImageCmd.Flags().BoolVar(&imgDaemon, "daemon", false, "Cache image from docker daemon")
|
||||
loadImageCmd.Flags().BoolVar(&imgRemote, "remote", false, "Cache image from remote registry")
|
||||
imageCmd.AddCommand(listImageCmd)
|
||||
}
|
||||
|
|
|
@ -239,6 +239,24 @@ func (r *Containerd) ImageExists(name string, sha string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// ListImages lists images managed by this container runtime
|
||||
func (r *Containerd) ListImages(ListImagesOptions) ([]string, error) {
|
||||
c := exec.Command("sudo", "ctr", "-n=k8s.io", "images", "list", "--quiet")
|
||||
rr, err := r.Runner.RunCmd(c)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ctr images list")
|
||||
}
|
||||
all := strings.Split(rr.Stdout.String(), "\n")
|
||||
imgs := []string{}
|
||||
for _, img := range all {
|
||||
if img == "" || strings.Contains(img, "sha256:") {
|
||||
continue
|
||||
}
|
||||
imgs = append(imgs, img)
|
||||
}
|
||||
return imgs, nil
|
||||
}
|
||||
|
||||
// LoadImage loads an image into this runtime
|
||||
func (r *Containerd) LoadImage(path string) error {
|
||||
klog.Infof("Loading image: %s", path)
|
||||
|
|
|
@ -167,6 +167,16 @@ func (r *CRIO) ImageExists(name string, sha string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// ListImages returns a list of images managed by this container runtime
|
||||
func (r *CRIO) ListImages(ListImagesOptions) ([]string, error) {
|
||||
c := exec.Command("sudo", "podman", "images", "--format", "{{.Repository}}:{{.Tag}}")
|
||||
rr, err := r.Runner.RunCmd(c)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "podman images")
|
||||
}
|
||||
return strings.Split(strings.TrimSpace(rr.Stdout.String()), "\n"), nil
|
||||
}
|
||||
|
||||
// LoadImage loads an image into this runtime
|
||||
func (r *CRIO) LoadImage(path string) error {
|
||||
klog.Infof("Loading image: %s", path)
|
||||
|
|
|
@ -98,6 +98,8 @@ type Manager interface {
|
|||
|
||||
// ImageExists takes image name and image sha checks if an it exists
|
||||
ImageExists(string, string) bool
|
||||
// ListImages returns a list of images managed by this container runtime
|
||||
ListImages(ListImagesOptions) ([]string, error)
|
||||
|
||||
// RemoveImage remove image based on name
|
||||
RemoveImage(string) error
|
||||
|
@ -148,6 +150,10 @@ type ListContainersOptions struct {
|
|||
Namespaces []string
|
||||
}
|
||||
|
||||
// ListImageOptions are the options to use for listing images
|
||||
type ListImagesOptions struct {
|
||||
}
|
||||
|
||||
// ErrContainerRuntimeNotRunning is thrown when container runtime is not running
|
||||
var ErrContainerRuntimeNotRunning = errors.New("container runtime is not running")
|
||||
|
||||
|
|
|
@ -162,6 +162,25 @@ func (r *Docker) ImageExists(name string, sha string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// ListImages returns a list of images managed by this container runtime
|
||||
func (r *Docker) ListImages(ListImagesOptions) ([]string, error) {
|
||||
c := exec.Command("docker", "images", "--format", "{{.Repository}}:{{.Tag}}")
|
||||
rr, err := r.Runner.RunCmd(c)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "docker images")
|
||||
}
|
||||
short := strings.Split(rr.Stdout.String(), "\n")
|
||||
imgs := []string{}
|
||||
for _, img := range short {
|
||||
if img == "" {
|
||||
continue
|
||||
}
|
||||
img = addDockerIO(img)
|
||||
imgs = append(imgs, img)
|
||||
}
|
||||
return imgs, nil
|
||||
}
|
||||
|
||||
// LoadImage loads an image into this runtime
|
||||
func (r *Docker) LoadImage(path string) error {
|
||||
klog.Infof("Loading image: %s", path)
|
||||
|
@ -446,6 +465,29 @@ func dockerImagesPreloaded(runner command.Runner, images []string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// Add docker.io prefix
|
||||
func addDockerIO(name string) string {
|
||||
var reg, usr, img string
|
||||
p := strings.SplitN(name, "/", 2)
|
||||
if len(p) > 1 && strings.Contains(p[0], ".") {
|
||||
reg = p[0]
|
||||
img = p[1]
|
||||
} else {
|
||||
reg = "docker.io"
|
||||
img = name
|
||||
p = strings.SplitN(img, "/", 2)
|
||||
if len(p) > 1 {
|
||||
usr = p[0]
|
||||
img = p[1]
|
||||
} else {
|
||||
usr = "library"
|
||||
img = name
|
||||
}
|
||||
return reg + "/" + usr + "/" + img
|
||||
}
|
||||
return reg + "/" + img
|
||||
}
|
||||
|
||||
// Remove docker.io prefix since it won't be included in images names
|
||||
// when we call 'docker images'
|
||||
func trimDockerIO(name string) string {
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -372,3 +373,54 @@ func RemoveImages(images []string, profile *config.Profile) error {
|
|||
klog.Infof("failed removing from: %s", strings.Join(failed, " "))
|
||||
return nil
|
||||
}
|
||||
|
||||
func ListImages(profile *config.Profile) error {
|
||||
api, err := NewAPIClient()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error creating api client")
|
||||
}
|
||||
defer api.Close()
|
||||
|
||||
pName := profile.Name
|
||||
|
||||
c, err := config.Load(pName)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to load profile %q: %v", pName, err)
|
||||
return errors.Wrapf(err, "error loading config for profile :%v", pName)
|
||||
}
|
||||
|
||||
for _, n := range c.Nodes {
|
||||
m := config.MachineName(*c, n)
|
||||
|
||||
status, err := Status(api, m)
|
||||
if err != nil {
|
||||
klog.Warningf("error getting status for %s: %v", m, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if status == state.Running.String() {
|
||||
h, err := api.Load(m)
|
||||
if err != nil {
|
||||
klog.Warningf("Failed to load machine %q: %v", m, err)
|
||||
continue
|
||||
}
|
||||
runner, err := CommandRunner(h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cr, err := cruntime.New(cruntime.Config{Type: c.KubernetesConfig.ContainerRuntime, Runner: runner})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error creating container runtime")
|
||||
}
|
||||
list, err := cr.ListImages(cruntime.ListImagesOptions{})
|
||||
if err != nil {
|
||||
klog.Warningf("Failed to list images for profile %s %v", pName, err.Error())
|
||||
continue
|
||||
}
|
||||
sort.Sort(sort.Reverse(sort.StringSlice(list)))
|
||||
fmt.Printf(strings.Join(list, "\n") + "\n")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -246,6 +246,7 @@ var (
|
|||
GuestCert = Kind{ID: "GUEST_CERT", ExitCode: ExGuestError}
|
||||
GuestCpConfig = Kind{ID: "GUEST_CP_CONFIG", ExitCode: ExGuestConfig}
|
||||
GuestDeletion = Kind{ID: "GUEST_DELETION", ExitCode: ExGuestError}
|
||||
GuestImageList = Kind{ID: "GUEST_IMAGE_LIST", ExitCode: ExGuestError}
|
||||
GuestImageLoad = Kind{ID: "GUEST_IMAGE_LOAD", ExitCode: ExGuestError}
|
||||
GuestImageRemove = Kind{ID: "GUEST_IMAGE_REMOVE", ExitCode: ExGuestError}
|
||||
GuestLoadHost = Kind{ID: "GUEST_LOAD_HOST", ExitCode: ExGuestError}
|
||||
|
|
|
@ -70,6 +70,52 @@ minikube image help [command] [flags]
|
|||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
||||
## minikube image list
|
||||
|
||||
List images
|
||||
|
||||
### Synopsis
|
||||
|
||||
List images
|
||||
|
||||
```shell
|
||||
minikube image list [flags]
|
||||
```
|
||||
|
||||
### Aliases
|
||||
|
||||
[ls]
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
|
||||
$ minikube image list
|
||||
|
||||
```
|
||||
|
||||
### 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 image into minikube
|
||||
|
|
Loading…
Reference in New Issue