Add dangling image reference on delete when last image has children

Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
Derek McGowan 2023-12-18 12:48:38 -08:00
parent 0c6e9121b2
commit cf1ea9237c
No known key found for this signature in database
GPG key ID: F58C5D0A4405ACDB
2 changed files with 23 additions and 2 deletions

View file

@ -5,7 +5,9 @@ import (
"fmt"
"sort"
"strings"
"time"
cerrdefs "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images"
"github.com/containerd/log"
"github.com/distribution/reference"
@ -135,7 +137,7 @@ func (i *ImageService) ImageDelete(ctx context.Context, imageRef string, force,
}
}
return records, nil
} else if !force {
} else if len(all) > 1 && !force {
// Since only a single used reference, remove all active
// TODO: Consider keeping the conflict and changing active
// reference calculation in image checker.
@ -145,6 +147,7 @@ func (i *ImageService) ImageDelete(ctx context.Context, imageRef string, force,
using := func(c *container.Container) bool {
return c.ImageID == imgID
}
// TODO: Should this also check parentage here?
ctr := i.containers.First(using)
if ctr != nil {
familiarRef := reference.FamiliarString(parsedRef)
@ -372,6 +375,24 @@ func (i *ImageService) imageDeleteHelper(ctx context.Context, img images.Image,
return err
}
if !isDanglingImage(img) && len(all) == 1 && extra&conflictActiveReference != 0 {
children, err := i.Children(ctx, imgID)
if err != nil {
return err
}
if len(children) > 0 {
img := images.Image{
Name: danglingImageName(img.Target.Digest),
Target: img.Target,
CreatedAt: time.Now(),
Labels: img.Labels,
}
if _, err = i.client.ImageService().Create(ctx, img); err != nil && !cerrdefs.IsAlreadyExists(err) {
return fmt.Errorf("failed to create dangling image: %w", err)
}
}
}
// TODO: Add target option
err = i.images.Delete(ctx, img.Name, images.SynchronousDelete())
if err != nil {

View file

@ -295,7 +295,7 @@ RUN echo 2 #layer2
// should not be untagged without the -f flag
assert.ErrorContains(c, err, "")
assert.Assert(c, strings.Contains(out, cID[:12]))
assert.Assert(c, strings.Contains(out, "(must force)"))
assert.Assert(c, strings.Contains(out, "(must force)") || strings.Contains(out, "(must be forced)"))
// Add the -f flag and test again.
out = cli.DockerCmd(c, "rmi", "-f", newTag).Combined()
// should be allowed to untag with the -f flag