Switch to ImageServer.UntagImage in RemoveImage handler

Add an UntagImage() method to pkg/storage/ImageServer, which will check
if the passed-in NameOrID is a name.  If so, it merely removes that name
from the image, removing the image only if it was the last name that the
image had.  If the NameOrID is an image ID, the image is removed, as
RemoveImage() does.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
This commit is contained in:
Nalin Dahyabhai 2017-10-30 17:18:42 -04:00
parent 3f2bc09231
commit 2e5e92730a
4 changed files with 137 additions and 9 deletions

View file

@ -4,7 +4,7 @@ import (
"errors"
"fmt"
"net"
"path/filepath"
"path"
"regexp"
"strings"
@ -51,6 +51,9 @@ type ImageServer interface {
ImageStatus(systemContext *types.SystemContext, filter string) (*ImageResult, error)
// PullImage imports an image from the specified location.
PullImage(systemContext *types.SystemContext, imageName string, options *copy.Options) (types.ImageReference, error)
// UntagImage removes a name from the specified image, and if it was
// the only name the image had, removes the image.
UntagImage(systemContext *types.SystemContext, imageName string) error
// RemoveImage deletes the specified image.
RemoveImage(systemContext *types.SystemContext, imageName string) error
// GetStore returns the reference to the storage library Store which
@ -263,6 +266,57 @@ func (svc *imageService) PullImage(systemContext *types.SystemContext, imageName
return destRef, nil
}
func (svc *imageService) UntagImage(systemContext *types.SystemContext, nameOrID string) error {
ref, err := alltransports.ParseImageName(nameOrID)
if err != nil {
ref2, err2 := istorage.Transport.ParseStoreReference(svc.store, "@"+nameOrID)
if err2 != nil {
ref3, err3 := istorage.Transport.ParseStoreReference(svc.store, nameOrID)
if err3 != nil {
return err
}
ref2 = ref3
}
ref = ref2
}
img, err := istorage.Transport.GetStoreImage(svc.store, ref)
if err != nil {
return err
}
if nameOrID != img.ID {
namedRef, err := svc.prepareImage(nameOrID, &copy.Options{})
if err != nil {
return err
}
name := nameOrID
if namedRef.DockerReference() != nil {
name = namedRef.DockerReference().Name()
if tagged, ok := namedRef.DockerReference().(reference.NamedTagged); ok {
name = name + ":" + tagged.Tag()
}
if canonical, ok := namedRef.DockerReference().(reference.Canonical); ok {
name = name + "@" + canonical.Digest().String()
}
}
prunedNames := make([]string, 0, len(img.Names))
for _, imgName := range img.Names {
if imgName != name && imgName != nameOrID {
prunedNames = append(prunedNames, imgName)
}
}
if len(prunedNames) > 0 {
return svc.store.SetNames(img.ID, prunedNames)
}
}
return ref.DeleteImage(systemContext)
}
func (svc *imageService) RemoveImage(systemContext *types.SystemContext, nameOrID string) error {
ref, err := alltransports.ParseImageName(nameOrID)
if err != nil {
@ -440,7 +494,7 @@ func (svc *imageService) ResolveNames(imageName string) ([]string, error) {
_, rest := splitDomain(r.Name())
images := []string{}
for _, r := range svc.registries {
images = append(images, filepath.Join(r, rest))
images = append(images, path.Join(r, rest))
}
return images, nil
}