github.com/rawahars/moby@v24.0.4+incompatible/daemon/containerd/image_tag.go (about) 1 package containerd 2 3 import ( 4 "context" 5 6 cerrdefs "github.com/containerd/containerd/errdefs" 7 containerdimages "github.com/containerd/containerd/images" 8 "github.com/docker/distribution/reference" 9 "github.com/docker/docker/errdefs" 10 "github.com/docker/docker/image" 11 "github.com/pkg/errors" 12 "github.com/sirupsen/logrus" 13 ) 14 15 // TagImage creates an image named as newTag and targeting the given descriptor id. 16 func (i *ImageService) TagImage(ctx context.Context, imageID image.ID, newTag reference.Named) error { 17 target, err := i.resolveDescriptor(ctx, imageID.String()) 18 if err != nil { 19 return errors.Wrapf(err, "failed to resolve image id %q to a descriptor", imageID.String()) 20 } 21 22 newImg := containerdimages.Image{ 23 Name: newTag.String(), 24 Target: target, 25 } 26 27 is := i.client.ImageService() 28 _, err = is.Create(ctx, newImg) 29 if err != nil { 30 if !cerrdefs.IsAlreadyExists(err) { 31 return errdefs.System(errors.Wrapf(err, "failed to create image with name %s and target %s", newImg.Name, newImg.Target.Digest.String())) 32 } 33 34 replacedImg, err := is.Get(ctx, newImg.Name) 35 if err != nil { 36 return errdefs.Unknown(errors.Wrapf(err, "creating image %s failed because it already exists, but accessing it also failed", newImg.Name)) 37 } 38 39 // Check if image we would replace already resolves to the same target. 40 // No need to do anything. 41 if replacedImg.Target.Digest == target.Digest { 42 i.LogImageEvent(imageID.String(), reference.FamiliarString(newTag), "tag") 43 return nil 44 } 45 46 // If there already exists an image with this tag, delete it 47 if err := i.softImageDelete(ctx, replacedImg); err != nil { 48 return errors.Wrapf(err, "failed to delete previous image %s", replacedImg.Name) 49 } 50 51 if _, err = is.Create(context.Background(), newImg); err != nil { 52 return errdefs.System(errors.Wrapf(err, "failed to create an image %s with target %s after deleting the existing one", 53 newImg.Name, imageID.String())) 54 } 55 } 56 57 logger := logrus.WithFields(logrus.Fields{ 58 "imageID": imageID.String(), 59 "tag": newTag.String(), 60 }) 61 logger.Info("image created") 62 63 defer i.LogImageEvent(imageID.String(), reference.FamiliarString(newTag), "tag") 64 65 // The tag succeeded, check if the source image is dangling 66 sourceDanglingImg, err := is.Get(context.Background(), danglingImageName(target.Digest)) 67 if err != nil { 68 if !cerrdefs.IsNotFound(err) { 69 logger.WithError(err).Warn("unexpected error when checking if source image is dangling") 70 } 71 72 return nil 73 } 74 75 // Delete the source dangling image, as it's no longer dangling. 76 if err := is.Delete(context.Background(), sourceDanglingImg.Name); err != nil { 77 logger.WithError(err).Warn("unexpected error when deleting dangling image") 78 } 79 80 return nil 81 }