Skip to content

pull,load: use *Image instead of re-resolving via name #2339

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 21, 2025
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
33 changes: 31 additions & 2 deletions libimage/copier.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ import (
"github.com/containers/image/v5/signature"
"github.com/containers/image/v5/signature/signer"
storageTransport "github.com/containers/image/v5/storage"
"github.com/containers/image/v5/transports"
"github.com/containers/image/v5/types"
encconfig "github.com/containers/ocicrypt/config"
"github.com/containers/storage"
"github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -175,8 +177,8 @@ type Copier struct {
// newCopier creates a Copier based on a runtime's system context.
// Note that fields in options *may* overwrite the counterparts of
// the specified system context. Please make sure to call `(*Copier).Close()`.
func (r *Runtime) newCopier(options *CopyOptions, reportResolvedReference *types.ImageReference) (*Copier, error) {
return NewCopier(options, r.SystemContext(), reportResolvedReference)
func (r *Runtime) newCopier(options *CopyOptions) (*Copier, error) {
return NewCopier(options, r.SystemContext(), nil)
}

// storageAllowedPolicyScopes overrides the policy for local storage
Expand Down Expand Up @@ -350,6 +352,12 @@ func (c *Copier) Close() error {
// Copy the source to the destination. Returns the bytes of the copied
// manifest which may be used for digest computation.
func (c *Copier) Copy(ctx context.Context, source, destination types.ImageReference) ([]byte, error) {
return c.copyInternal(ctx, source, destination, nil)
}

// Copy the source to the destination. Returns the bytes of the copied
// manifest which may be used for digest computation.
func (c *Copier) copyInternal(ctx context.Context, source, destination types.ImageReference, reportResolvedReference *types.ImageReference) ([]byte, error) {
logrus.Debugf("Copying source image %s to destination image %s", source.StringWithinTransport(), destination.StringWithinTransport())

// Avoid running out of time when running inside a systemd unit by
Expand Down Expand Up @@ -454,6 +462,11 @@ func (c *Copier) Copy(ctx context.Context, source, destination types.ImageRefere
var returnManifest []byte
f := func() error {
opts := c.imageCopyOptions
// This is already set when `newCopier` was called but there is an option
// to override it by callers if needed.
if reportResolvedReference != nil {
opts.ReportResolvedReference = reportResolvedReference
}
if sourceInsecure != nil {
value := types.NewOptionalBool(*sourceInsecure)
opts.SourceCtx.DockerInsecureSkipTLSVerify = value
Expand All @@ -472,6 +485,22 @@ func (c *Copier) Copy(ctx context.Context, source, destination types.ImageRefere
return returnManifest, retry.IfNecessary(ctx, f, &c.retryOptions)
}

func (c *Copier) copyToStorage(ctx context.Context, source, destination types.ImageReference) (*storage.Image, error) {
var resolvedReference types.ImageReference
_, err := c.copyInternal(ctx, source, destination, &resolvedReference)
if err != nil {
return nil, fmt.Errorf("internal error: unable to copy from source %s: %w", source, err)
}
if resolvedReference == nil {
return nil, fmt.Errorf("internal error: After attempting to copy %s, resolvedReference is nil", source)
}
_, image, err := storageTransport.ResolveReference(resolvedReference)
if err != nil {
return nil, fmt.Errorf("resolving an already-resolved reference %q to the pulled image: %w", transports.ImageName(resolvedReference), err)
}
return image, nil
}

// checkRegistrySourcesAllows checks the $BUILD_REGISTRY_SOURCES environment
// variable, if it's set. The contents are expected to be a JSON-encoded
// github.com/openshift/api/config/v1.Image, set by an OpenShift build
Expand Down
6 changes: 1 addition & 5 deletions libimage/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,11 @@ func TestImageFunctions(t *testing.T) {
// Just make sure that the ID has 64 characters.
require.True(t, len(image.ID()) == 64, "ID should be 64 characters long")

// Make sure that the image we pulled by digest is the same one we
// pulled by tag.
require.Equal(t, origDigest.String(), image.Digest().String(), "digests of pulled images should match")

// NOTE: we're recording two digests. One for the image and one for the
// manifest list we chose it from.
digests := image.Digests()
require.Len(t, digests, 2)
require.Equal(t, origDigest.String(), digests[0].String(), "first recorded digest should be the one of the image")
require.Contains(t, digests, origDigest, "original digest string should be present in the digests array of new pulled image")

// containers/podman/issues/12729: make sure manifest lookup returns
// the correct error for both digests.
Expand Down
2 changes: 1 addition & 1 deletion libimage/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func (r *Runtime) Import(ctx context.Context, path string, options *ImportOption
return "", err
}

c, err := r.newCopier(&options.CopyOptions, nil)
c, err := r.newCopier(&options.CopyOptions)
if err != nil {
return "", err
}
Expand Down
10 changes: 7 additions & 3 deletions libimage/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func (r *Runtime) doLoadReference(ctx context.Context, ref types.ImageReference,
case dockerArchiveTransport.Transport.Name():
images, err = r.loadMultiImageDockerArchive(ctx, ref, &options.CopyOptions)
default:
images, err = r.copyFromDefault(ctx, ref, &options.CopyOptions)
_, images, err = r.copyFromDefault(ctx, ref, &options.CopyOptions)
}
return images, ref.Transport().Name(), err
}
Expand All @@ -49,6 +49,9 @@ func (r *Runtime) LoadReference(ctx context.Context, ref types.ImageReference, o
// Load loads one or more images (depending on the transport) from the
// specified path. The path may point to an image the following transports:
// oci, oci-archive, dir, docker-archive.
//
// Load returns a string slice with names of recently loaded images.
// If images are unnamed in the source, it returns a string slice of image IDs instead.
func (r *Runtime) Load(ctx context.Context, path string, options *LoadOptions) ([]string, error) {
logrus.Debugf("Loading image from %q", path)

Expand Down Expand Up @@ -142,7 +145,8 @@ func (r *Runtime) loadMultiImageDockerArchive(ctx context.Context, ref types.Ima
// should.
path := ref.StringWithinTransport()
if err := fileutils.Exists(path); err != nil {
return r.copyFromDockerArchive(ctx, ref, options)
_, names, err := r.copyFromDockerArchive(ctx, ref, options)
return names, err
}

reader, err := dockerArchiveTransport.NewReader(r.systemContextCopy(), path)
Expand All @@ -163,7 +167,7 @@ func (r *Runtime) loadMultiImageDockerArchive(ctx context.Context, ref types.Ima
var copiedImages []string
for _, list := range refLists {
for _, listRef := range list {
names, err := r.copyFromDockerArchiveReaderReference(ctx, reader, listRef, options)
_, names, err := r.copyFromDockerArchiveReaderReference(ctx, reader, listRef, options)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion libimage/manifest_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ func (m *ManifestList) Push(ctx context.Context, destination string, options *Ma
// NOTE: we're using the logic in copier to create a proper
// types.SystemContext. This prevents us from having an error prone
// code duplicate here.
copier, err := m.image.runtime.newCopier(&options.CopyOptions, nil)
copier, err := m.image.runtime.newCopier(&options.CopyOptions)
if err != nil {
return "", err
}
Expand Down
Loading