Add ListImages function and image list command

pull/11007/head
Anders F Björklund 2021-04-06 22:40:06 +02:00
parent db3fd51194
commit 35d8d4aa52
8 changed files with 194 additions and 0 deletions

View File

@ -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)
}

View File

@ -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)

View File

@ -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)

View File

@ -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")

View File

@ -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 {

View File

@ -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
}

View File

@ -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}

View File

@ -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