cri-o/cmd/kpod/rmi.go

124 lines
3 KiB
Go
Raw Normal View History

package main
import (
"fmt"
"github.com/containers/storage"
"github.com/kubernetes-incubator/cri-o/libpod/images"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
var (
rmiDescription = "removes one or more locally stored images."
rmiFlags = []cli.Flag{
cli.BoolFlag{
Name: "force, f",
Usage: "force removal of the image",
},
}
rmiCommand = cli.Command{
Name: "rmi",
Usage: "removes one or more images from local storage",
Description: rmiDescription,
Action: rmiCmd,
ArgsUsage: "IMAGE-NAME-OR-ID [...]",
Flags: rmiFlags,
}
)
func rmiCmd(c *cli.Context) error {
force := false
if c.IsSet("force") {
force = c.Bool("force")
}
args := c.Args()
if len(args) == 0 {
return errors.Errorf("image name or ID must be specified")
}
config, err := getConfig(c)
if err != nil {
return errors.Wrapf(err, "Could not get config")
}
store, err := getStore(config)
if err != nil {
return err
}
for _, id := range args {
image, err := images.FindImage(store, id)
if err != nil {
return errors.Wrapf(err, "could not get image %q", id)
}
if image != nil {
ctrIDs, err := runningContainers(image, store)
if err != nil {
return errors.Wrapf(err, "error getting running containers for image %q", id)
}
if len(ctrIDs) > 0 && len(image.Names) <= 1 {
if force {
removeContainers(ctrIDs, store)
} else {
for ctrID := range ctrIDs {
return fmt.Errorf("Could not remove image %q (must force) - container %q is using its reference image", id, ctrID)
}
}
}
// If the user supplied an ID, we cannot delete the image if it is referred to by multiple tags
if images.MatchesID(image.ID, id) {
if len(image.Names) > 1 && !force {
return fmt.Errorf("unable to delete %s (must force) - image is referred to in multiple tags", image.ID)
}
// If it is forced, we have to untag the image so that it can be deleted
image.Names = image.Names[:0]
} else {
name, err2 := images.UntagImage(store, image, id)
if err2 != nil {
return err
}
fmt.Printf("untagged: %s", name)
}
if len(image.Names) > 0 {
continue
}
id, err := images.RemoveImage(image, store)
if err != nil {
return err
}
fmt.Printf("%s\n", id)
}
}
return nil
}
// Returns a list of running containers associated with the given ImageReference
// TODO: replace this with something in libkpod
func runningContainers(image *storage.Image, store storage.Store) ([]string, error) {
ctrIDs := []string{}
containers, err := store.Containers()
if err != nil {
return nil, err
}
for _, ctr := range containers {
if ctr.ImageID == image.ID {
ctrIDs = append(ctrIDs, ctr.ID)
}
}
return ctrIDs, nil
}
// TODO: replace this with something in libkpod
func removeContainers(ctrIDs []string, store storage.Store) error {
for _, ctrID := range ctrIDs {
if err := store.DeleteContainer(ctrID); err != nil {
return errors.Wrapf(err, "could not remove container %q", ctrID)
}
}
return nil
}