Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 17 additions & 95 deletions daemon/containerd/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ var shortID = regexp.MustCompile(`^([a-f0-9]{4,64})$`)

// GetContainerdImage returns the containerd image corresponding to the image referred to by refOrID.
// The platform parameter is currently ignored
func (i *ImageService) GetContainerdImage(ctx context.Context, refOrID string, platform *ocispec.Platform) (containerdimages.Image, error) {
return i.resolveImageName2(ctx, refOrID)
func (i *ImageService) GetContainerdImage(ctx context.Context, refOrID string, platform *ocispec.Platform) (img containerdimages.Image, err error) {
return i.resolveImage(ctx, refOrID)
}

// GetImage returns an image corresponding to the image referred to by refOrID.
Expand Down Expand Up @@ -68,12 +68,13 @@ func (i *ImageService) GetImage(ctx context.Context, refOrID string, options ima
}

func (i *ImageService) getImage(ctx context.Context, refOrID string) (containerd.Image, *image.Image, error) {
desc, err := i.ResolveImage(ctx, refOrID)
img, err := i.resolveImage(ctx, refOrID)
if err != nil {
return nil, nil, err
}

ctrdimg, err := i.resolveImageName2(ctx, refOrID)
// TODO(rumpl): pass the platform
ctrdimg, err := i.GetContainerdImage(ctx, refOrID, nil)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -108,7 +109,7 @@ func (i *ImageService) getImage(ctx context.Context, refOrID string) (containerd
}
return ii, &image.Image{
V1Image: image.V1Image{
ID: string(desc.Digest),
ID: string(img.Target.Digest),
OS: ociimage.OS,
Architecture: ociimage.Architecture,
Config: &containertypes.Config{
Expand All @@ -125,18 +126,13 @@ func (i *ImageService) getImage(ctx context.Context, refOrID string) (containerd
}, nil
}

// ResolveImage searches for an image based on the given
// resolveImage searches for an image based on the given
// reference or identifier. Returns the descriptor of
// the image, could be manifest list, manifest, or config.
func (i *ImageService) ResolveImage(ctx context.Context, refOrID string) (d ocispec.Descriptor, err error) {
d, _, err = i.resolveImageName(ctx, refOrID)
return
}

func (i *ImageService) resolveImageName2(ctx context.Context, refOrID string) (img containerdimages.Image, err error) {
func (i *ImageService) resolveImage(ctx context.Context, refOrID string) (img containerdimages.Image, err error) {
parsed, err := reference.ParseAnyReference(refOrID)
if err != nil {
return img, errdefs.InvalidParameter(err)
return containerdimages.Image{}, errdefs.InvalidParameter(err)
}

is := i.client.ImageService()
Expand All @@ -145,15 +141,15 @@ func (i *ImageService) resolveImageName2(ctx context.Context, refOrID string) (i
if !ok {
digested, ok := parsed.(reference.Digested)
if !ok {
return img, errdefs.InvalidParameter(errors.New("bad reference"))
return containerdimages.Image{}, errdefs.InvalidParameter(errors.New("bad reference"))
}

imgs, err := is.List(ctx, fmt.Sprintf("target.digest==%s", digested.Digest()))
if err != nil {
return img, errors.Wrap(err, "failed to lookup digest")
return containerdimages.Image{}, errors.Wrap(err, "failed to lookup digest")
}
if len(imgs) == 0 {
return img, errdefs.NotFound(errors.New("image not found with digest"))
return containerdimages.Image{}, errdefs.NotFound(errors.New("image not found with digest"))
}

return imgs[0], nil
Expand All @@ -170,11 +166,11 @@ func (i *ImageService) resolveImageName2(ctx context.Context, refOrID string) (i
}
imgs, err := is.List(ctx, filters...)
if err != nil {
return img, err
return containerdimages.Image{}, err
}

if len(imgs) == 0 {
return img, errdefs.NotFound(errors.New("list returned no images"))
return containerdimages.Image{}, errdefs.NotFound(errors.New("list returned no images"))
}
if len(imgs) > 1 {
digests := map[digest.Digest]struct{}{}
Expand All @@ -186,7 +182,7 @@ func (i *ImageService) resolveImageName2(ctx context.Context, refOrID string) (i
}

if len(digests) > 1 {
return img, errdefs.NotFound(errors.New("ambiguous reference"))
return containerdimages.Image{}, errdefs.NotFound(errors.New("ambiguous reference"))
}
}

Expand All @@ -199,88 +195,14 @@ func (i *ImageService) resolveImageName2(ctx context.Context, refOrID string) (i
if err != nil {
// TODO(containerd): error translation can use common function
if !cerrdefs.IsNotFound(err) {
return img, err
return containerdimages.Image{}, err
}
return img, errdefs.NotFound(errors.New("id not found"))
return containerdimages.Image{}, errdefs.NotFound(errors.New("id not found"))
}

return img, nil
}

func (i *ImageService) resolveImageName(ctx context.Context, refOrID string) (ocispec.Descriptor, reference.Named, error) {
parsed, err := reference.ParseAnyReference(refOrID)
if err != nil {
return ocispec.Descriptor{}, nil, errdefs.InvalidParameter(err)
}

is := i.client.ImageService()

namedRef, ok := parsed.(reference.Named)
if !ok {
digested, ok := parsed.(reference.Digested)
if !ok {
return ocispec.Descriptor{}, nil, errdefs.InvalidParameter(errors.New("bad reference"))
}

imgs, err := is.List(ctx, fmt.Sprintf("target.digest==%s", digested.Digest()))
if err != nil {
return ocispec.Descriptor{}, nil, errors.Wrap(err, "failed to lookup digest")
}
if len(imgs) == 0 {
return ocispec.Descriptor{}, nil, errdefs.NotFound(errors.New("image not found with digest"))
}

return imgs[0].Target, nil, nil
}

namedRef = reference.TagNameOnly(namedRef)

// If the identifier could be a short ID, attempt to match
if shortID.MatchString(refOrID) {
ref := namedRef.String()
filters := []string{
fmt.Sprintf("name==%q", ref),
fmt.Sprintf(`target.digest~=/sha256:%s[0-9a-fA-F]{%d}/`, refOrID, 64-len(refOrID)),
}
imgs, err := is.List(ctx, filters...)
if err != nil {
return ocispec.Descriptor{}, nil, err
}

if len(imgs) == 0 {
return ocispec.Descriptor{}, nil, errdefs.NotFound(errors.New("list returned no images"))
}
if len(imgs) > 1 {
digests := map[digest.Digest]struct{}{}
for _, img := range imgs {
if img.Name == ref {
return img.Target, namedRef, nil
}
digests[img.Target.Digest] = struct{}{}
}

if len(digests) > 1 {
return ocispec.Descriptor{}, nil, errdefs.NotFound(errors.New("ambiguous reference"))
}
}

if imgs[0].Name != ref {
namedRef = nil
}
return imgs[0].Target, namedRef, nil
}
img, err := is.Get(ctx, namedRef.String())
if err != nil {
// TODO(containerd): error translation can use common function
if !cerrdefs.IsNotFound(err) {
return ocispec.Descriptor{}, nil, err
}
return ocispec.Descriptor{}, nil, errdefs.NotFound(errors.New("id not found"))
}

return img.Target, namedRef, nil
}

// PresentChildrenHandler traverses recursively all children descriptors that are present in the store.
func (i *ImageService) presentChildrenHandler() containerdimages.HandlerFunc {
store := i.client.ContentStore()
Expand Down
4 changes: 2 additions & 2 deletions daemon/containerd/image_tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
// TagImage creates the tag specified by newTag, pointing to the image named
// imageName (alternatively, imageName can also be an image ID).
func (i *ImageService) TagImage(ctx context.Context, imageName, repository, tag string) (string, error) {
desc, err := i.ResolveImage(ctx, imageName)
img, err := i.resolveImage(ctx, imageName)
if err != nil {
return "", err
}
Expand All @@ -27,7 +27,7 @@ func (i *ImageService) TagImage(ctx context.Context, imageName, repository, tag
}
}

err = i.TagImageWithReference(ctx, image.ID(desc.Digest), newTag)
err = i.TagImageWithReference(ctx, image.ID(img.Target.Digest), newTag)
return reference.FamiliarString(newTag), err
}

Expand Down