Add --accept-repositories integration tests

This adds the integration tests for the repository or namespaced
registry feature introduced in c/common.

Signed-off-by: Sascha Grunert <sgrunert@redhat.com>
This commit is contained in:
Sascha Grunert
2021-07-20 12:20:43 +02:00
parent a5de831418
commit 732ece6ae2
17 changed files with 462 additions and 89 deletions

View File

@ -342,7 +342,7 @@ func (c *copier) copy(ctx context.Context, source, destination types.ImageRefere
}
}
var copiedManifest []byte
var returnManifest []byte
f := func() error {
opts := c.imageCopyOptions
if sourceInsecure != nil {
@ -354,11 +354,13 @@ func (c *copier) copy(ctx context.Context, source, destination types.ImageRefere
opts.DestinationCtx.DockerInsecureSkipTLSVerify = value
}
var err error
copiedManifest, err = copy.Image(ctx, c.policyContext, destination, source, &opts)
copiedManifest, err := copy.Image(ctx, c.policyContext, destination, source, &opts)
if err == nil {
returnManifest = copiedManifest
}
return err
}
return copiedManifest, retry.RetryIfNecessary(ctx, f, &c.retryOptions)
return returnManifest, retry.RetryIfNecessary(ctx, f, &c.retryOptions)
}
// checkRegistrySourcesAllows checks the $BUILD_REGISTRY_SOURCES environment
@ -369,7 +371,7 @@ func (c *copier) copy(ctx context.Context, source, destination types.ImageRefere
// If set, the insecure return value indicates whether the registry is set to
// be insecure.
//
// NOTE: this functionality is required by Buildah.
// NOTE: this functionality is required by Buildah for OpenShift.
func checkRegistrySourcesAllows(dest types.ImageReference) (insecure *bool, err error) {
registrySources, ok := os.LookupEnv("BUILD_REGISTRY_SOURCES")
if !ok || registrySources == "" {

View File

@ -836,9 +836,9 @@ func (i *Image) Manifest(ctx context.Context) (rawManifest []byte, mimeType stri
return src.GetManifest(ctx, nil)
}
// getImageDigest creates an image object and uses the hex value of the digest as the image ID
// for parsing the store reference
func getImageDigest(ctx context.Context, src types.ImageReference, sys *types.SystemContext) (string, error) {
// getImageID creates an image object and uses the hex value of the config
// blob's digest (if it has one) as the image ID for parsing the store reference
func getImageID(ctx context.Context, src types.ImageReference, sys *types.SystemContext) (string, error) {
newImg, err := src.NewImage(ctx, sys)
if err != nil {
return "", err
@ -852,5 +852,5 @@ func getImageDigest(ctx context.Context, src types.ImageReference, sys *types.Sy
if err = imageDigest.Validate(); err != nil {
return "", errors.Wrapf(err, "error getting config info")
}
return "@" + imageDigest.Hex(), nil
return "@" + imageDigest.Encoded(), nil
}

View File

@ -86,7 +86,7 @@ func (r *Runtime) Import(ctx context.Context, path string, options *ImportOption
return "", err
}
id, err := getImageDigest(ctx, srcRef, r.systemContextCopy())
id, err := getImageID(ctx, srcRef, r.systemContextCopy())
if err != nil {
return "", err
}

View File

@ -18,6 +18,7 @@ import (
"github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
"github.com/containers/storage"
"github.com/containers/storage/pkg/lockfile"
digest "github.com/opencontainers/go-digest"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
@ -395,3 +396,20 @@ func (l *list) Remove(instanceDigest digest.Digest) error {
}
return err
}
// LockerForImage returns a Locker for a given image record. It's recommended
// that processes which use LoadFromImage() to load a list from an image and
// then use that list's SaveToImage() method to save a modified version of the
// list to that image record use this lock to avoid accidentally wiping out
// changes that another process is also attempting to make.
func LockerForImage(store storage.Store, image string) (lockfile.Locker, error) {
img, err := store.Image(image)
if err != nil {
return nil, errors.Wrapf(err, "locating image %q for locating lock", image)
}
d := digest.NewDigestFromEncoded(digest.Canonical, img.ID)
if err := d.Validate(); err != nil {
return nil, errors.Wrapf(err, "coercing image ID for %q into a digest", image)
}
return store.GetDigestLock(d)
}

View File

@ -12,6 +12,7 @@ import (
dockerArchiveTransport "github.com/containers/image/v5/docker/archive"
dockerDaemonTransport "github.com/containers/image/v5/docker/daemon"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/manifest"
ociArchiveTransport "github.com/containers/image/v5/oci/archive"
ociTransport "github.com/containers/image/v5/oci/layout"
"github.com/containers/image/v5/pkg/shortnames"
@ -19,6 +20,7 @@ import (
"github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
"github.com/containers/storage"
digest "github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@ -192,19 +194,19 @@ func (r *Runtime) copyFromDefault(ctx context.Context, ref types.ImageReference,
imageName = storageName
case ociArchiveTransport.Transport.Name():
manifest, err := ociArchiveTransport.LoadManifestDescriptor(ref)
manifestDescriptor, err := ociArchiveTransport.LoadManifestDescriptor(ref)
if err != nil {
return nil, err
}
// if index.json has no reference name, compute the image digest instead
if manifest.Annotations == nil || manifest.Annotations["org.opencontainers.image.ref.name"] == "" {
storageName, err = getImageDigest(ctx, ref, nil)
// if index.json has no reference name, compute the image ID instead
if manifestDescriptor.Annotations == nil || manifestDescriptor.Annotations["org.opencontainers.image.ref.name"] == "" {
storageName, err = getImageID(ctx, ref, nil)
if err != nil {
return nil, err
}
imageName = "sha256:" + storageName[1:]
} else {
storageName = manifest.Annotations["org.opencontainers.image.ref.name"]
storageName = manifestDescriptor.Annotations["org.opencontainers.image.ref.name"]
named, err := NormalizeName(storageName)
if err != nil {
return nil, err
@ -248,7 +250,7 @@ func (r *Runtime) storageReferencesReferencesFromArchiveReader(ctx context.Conte
var imageNames []string
if len(destNames) == 0 {
destName, err := getImageDigest(ctx, readerRef, &r.systemContext)
destName, err := getImageID(ctx, readerRef, &r.systemContext)
if err != nil {
return nil, nil, err
}
@ -316,8 +318,8 @@ func (r *Runtime) copyFromDockerArchiveReaderReference(ctx context.Context, read
}
// copyFromRegistry pulls the specified, possibly unqualified, name from a
// registry. On successful pull it returns the used fully-qualified name that
// can later be used to look up the image in the local containers storage.
// registry. On successful pull it returns the ID of the image in local
// storage.
//
// If options.All is set, all tags from the specified registry will be pulled.
func (r *Runtime) copyFromRegistry(ctx context.Context, ref types.ImageReference, inputName string, pullPolicy config.PullPolicy, options *PullOptions) ([]string, error) {
@ -337,7 +339,7 @@ func (r *Runtime) copyFromRegistry(ctx context.Context, ref types.ImageReference
return nil, err
}
pulledTags := []string{}
pulledIDs := []string{}
for _, tag := range tags {
select { // Let's be gentle with Podman remote.
case <-ctx.Done():
@ -353,15 +355,54 @@ func (r *Runtime) copyFromRegistry(ctx context.Context, ref types.ImageReference
if err != nil {
return nil, err
}
pulledTags = append(pulledTags, pulled...)
pulledIDs = append(pulledIDs, pulled...)
}
return pulledTags, nil
return pulledIDs, nil
}
// imageIDsForManifest() parses the manifest of the copied image and then looks
// up the IDs of the matching image. There's a small slice of time, between
// when we copy the image into local storage and when we go to look for it
// using the name that we gave it when we copied it, when the name we wanted to
// assign to the image could have been moved, but the image's ID will remain
// the same until it is deleted.
func (r *Runtime) imagesIDsForManifest(manifestBytes []byte, sys *types.SystemContext) ([]string, error) {
var imageDigest digest.Digest
manifestType := manifest.GuessMIMEType(manifestBytes)
if manifest.MIMETypeIsMultiImage(manifestType) {
list, err := manifest.ListFromBlob(manifestBytes, manifestType)
if err != nil {
return nil, errors.Wrapf(err, "parsing manifest list")
}
d, err := list.ChooseInstance(sys)
if err != nil {
return nil, errors.Wrapf(err, "choosing instance from manifest list")
}
imageDigest = d
} else {
d, err := manifest.Digest(manifestBytes)
if err != nil {
return nil, errors.Wrapf(err, "digesting manifest")
}
imageDigest = d
}
var results []string
images, err := r.store.ImagesByDigest(imageDigest)
if err != nil {
return nil, errors.Wrapf(err, "listing images by manifest digest")
}
for _, image := range images {
results = append(results, image.ID)
}
if len(results) == 0 {
return nil, errors.Wrapf(storage.ErrImageUnknown, "identifying new image by manifest digest")
}
return results, nil
}
// copySingleImageFromRegistry pulls the specified, possibly unqualified, name
// from a registry. On successful pull it returns the used fully-qualified
// name that can later be used to look up the image in the local containers
// from a registry. On successful pull it returns the ID of the image in local
// storage.
func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName string, pullPolicy config.PullPolicy, options *PullOptions) ([]string, error) { //nolint:gocyclo
// Sanity check.
@ -375,7 +416,7 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
err error
)
// Always check if there's a local image. If, we should use it's
// Always check if there's a local image. If so, we should use its
// resolved name for pulling. Assume we're doing a `pull foo`.
// If there's already a local image "localhost/foo", then we should
// attempt pulling that instead of doing the full short-name dance.
@ -454,7 +495,7 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
}
}
// If we found a local image, we should use it's locally resolved name
// If we found a local image, we should use its locally resolved name
// (see containers/buildah/issues/2904). An exception is if a custom
// platform is specified (e.g., `--arch=arm64`). In that case, we need
// to pessimistically pull the image since some images declare wrong
@ -462,7 +503,8 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
// containers/podman/issues/10682).
//
// In other words: multi-arch support can only be as good as the images
// in the wild.
// in the wild, so we shouldn't break things for our users by trying to
// insist that they make sense.
if localImage != nil && !customPlatform {
if imageName != resolvedImageName {
logrus.Debugf("Image %s resolved to local image %s which will be used for pulling", imageName, resolvedImageName)
@ -541,7 +583,8 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
return nil, err
}
}
if _, err := c.copy(ctx, srcRef, destRef); err != nil {
var manifestBytes []byte
if manifestBytes, err = c.copy(ctx, srcRef, destRef); err != nil {
logrus.Debugf("Error pulling candidate %s: %v", candidateString, err)
pullErrors = append(pullErrors, err)
continue
@ -554,6 +597,9 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
}
logrus.Debugf("Pulled candidate %s successfully", candidateString)
if ids, err := r.imagesIDsForManifest(manifestBytes, sys); err == nil {
return ids, nil
}
return []string{candidate.Value.String()}, nil
}

View File

@ -185,6 +185,10 @@ func (r *Runtime) searchImageInRegistry(ctx context.Context, term, registry stri
sys.DockerInsecureSkipTLSVerify = options.InsecureSkipTLSVerify
}
if options.Authfile != "" {
sys.AuthFilePath = options.Authfile
}
if options.ListTags {
results, err := searchRepositoryTags(ctx, sys, registry, term, options)
if err != nil {