-
Notifications
You must be signed in to change notification settings - Fork 787
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
Fix pulling of images within buildah #1319
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,12 +2,10 @@ package main | |
|
||
import ( | ||
"os" | ||
"strings" | ||
|
||
"github.com/containers/buildah" | ||
buildahcli "github.com/containers/buildah/pkg/cli" | ||
"github.com/containers/buildah/pkg/parse" | ||
"github.com/containers/buildah/util" | ||
"github.com/pkg/errors" | ||
"github.com/spf13/cobra" | ||
) | ||
|
@@ -81,27 +79,17 @@ func pullCmd(c *cobra.Command, args []string, iopts pullResults) error { | |
return err | ||
} | ||
|
||
transport := util.DefaultTransport | ||
arr := strings.SplitN(args[0], ":", 2) | ||
if len(arr) == 2 { | ||
if iopts.allTags { | ||
return errors.Errorf("tag can't be used with --all-tags") | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This check seems useful and worth preserving somewhere (though this implementation did not made little sense). AFAICS There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is tough to check, and seem fairly arbitrary. If I state I want to pull --alltags on alpine:latest, I don't see this as a big conflict. |
||
if _, ok := util.Transports[arr[0]]; ok { | ||
transport = arr[0] | ||
} | ||
} | ||
|
||
options := buildah.PullOptions{ | ||
Transport: transport, | ||
SignaturePolicyPath: iopts.signaturePolicy, | ||
Store: store, | ||
SystemContext: systemContext, | ||
BlobDirectory: iopts.blobCache, | ||
AllTags: iopts.allTags, | ||
ReportWriter: os.Stderr, | ||
} | ||
if !iopts.quiet { | ||
options.ReportWriter = os.Stderr | ||
|
||
if iopts.quiet { | ||
options.ReportWriter = nil // Turns off logging output | ||
} | ||
|
||
return buildah.Pull(getContext(), args[0], options) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,15 +28,14 @@ const ( | |
minimumTruncatedIDLength = 3 | ||
) | ||
|
||
func pullAndFindImage(ctx context.Context, store storage.Store, imageName string, options BuilderOptions, sc *types.SystemContext) (*storage.Image, types.ImageReference, error) { | ||
func pullAndFindImage(ctx context.Context, store storage.Store, transport string, imageName string, options BuilderOptions, sc *types.SystemContext) (*storage.Image, types.ImageReference, error) { | ||
pullOptions := PullOptions{ | ||
ReportWriter: options.ReportWriter, | ||
Store: store, | ||
SystemContext: options.SystemContext, | ||
Transport: options.Transport, | ||
BlobDirectory: options.PullBlobDirectory, | ||
} | ||
ref, err := pullImage(ctx, store, imageName, pullOptions, sc) | ||
ref, err := pullImage(ctx, store, transport, imageName, pullOptions, sc) | ||
if err != nil { | ||
logrus.Debugf("error pulling image %q: %v", imageName, err) | ||
return nil, nil, err | ||
|
@@ -101,55 +100,56 @@ func newContainerIDMappingOptions(idmapOptions *IDMappingOptions) storage.IDMapp | |
return options | ||
} | ||
|
||
func resolveImage(ctx context.Context, systemContext *types.SystemContext, store storage.Store, options BuilderOptions) (types.ImageReference, *storage.Image, error) { | ||
func resolveImage(ctx context.Context, systemContext *types.SystemContext, store storage.Store, options BuilderOptions) (types.ImageReference, string, *storage.Image, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (Ultimately I’d like more of the code to deal with the source as a |
||
type failure struct { | ||
resolvedImageName string | ||
err error | ||
} | ||
|
||
candidates, searchRegistriesWereUsedButEmpty, err := util.ResolveName(options.FromImage, options.Registry, systemContext, store) | ||
candidates, transport, searchRegistriesWereUsedButEmpty, err := util.ResolveName(options.FromImage, options.Registry, systemContext, store) | ||
if err != nil { | ||
return nil, nil, errors.Wrapf(err, "error parsing reference to image %q", options.FromImage) | ||
return nil, "", nil, errors.Wrapf(err, "error parsing reference to image %q", options.FromImage) | ||
} | ||
|
||
failures := []failure{} | ||
for _, image := range candidates { | ||
var err error | ||
if len(image) >= minimumTruncatedIDLength { | ||
if img, err := store.Image(image); err == nil && img != nil && strings.HasPrefix(img.ID, image) { | ||
ref, err := is.Transport.ParseStoreReference(store, img.ID) | ||
if err != nil { | ||
return nil, nil, errors.Wrapf(err, "error parsing reference to image %q", img.ID) | ||
return nil, "", nil, errors.Wrapf(err, "error parsing reference to image %q", img.ID) | ||
} | ||
return ref, img, nil | ||
return ref, transport, img, nil | ||
} | ||
} | ||
|
||
if options.PullPolicy == PullAlways { | ||
pulledImg, pulledReference, err := pullAndFindImage(ctx, store, image, options, systemContext) | ||
pulledImg, pulledReference, err := pullAndFindImage(ctx, store, transport, image, options, systemContext) | ||
if err != nil { | ||
logrus.Debugf("unable to pull and read image %q: %v", image, err) | ||
failures = append(failures, failure{resolvedImageName: image, err: err}) | ||
continue | ||
} | ||
return pulledReference, pulledImg, nil | ||
return pulledReference, transport, pulledImg, nil | ||
} | ||
|
||
srcRef, err := alltransports.ParseImageName(image) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don’t think we even need to try Parsing only the name part as transport2 Just always use the (Yes, this looks convoluted. (All of this is non-blocking, the ambiguity existed before this PR; this PR only makes the results of |
||
if err != nil { | ||
if options.Transport == "" { | ||
if transport == "" { | ||
logrus.Debugf("error parsing image name %q: %v", image, err) | ||
failures = append(failures, failure{ | ||
resolvedImageName: image, | ||
err: errors.Wrapf(err, "error parsing image name"), | ||
}) | ||
continue | ||
} | ||
logrus.Debugf("error parsing image name %q as given, trying with transport %q: %v", image, options.Transport, err) | ||
transport := options.Transport | ||
logrus.Debugf("error parsing image name %q as given, trying with transport %q: %v", image, transport, err) | ||
|
||
trans := transport | ||
if transport != util.DefaultTransport { | ||
transport = transport + ":" | ||
trans = trans + ":" | ||
} | ||
srcRef2, err := alltransports.ParseImageName(transport + image) | ||
srcRef2, err := alltransports.ParseImageName(trans + image) | ||
if err != nil { | ||
logrus.Debugf("error parsing image name %q: %v", transport+image, err) | ||
failures = append(failures, failure{ | ||
|
@@ -163,19 +163,19 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store | |
|
||
destImage, err := localImageNameForReference(ctx, store, srcRef, options.FromImage) | ||
if err != nil { | ||
return nil, nil, errors.Wrapf(err, "error computing local image name for %q", transports.ImageName(srcRef)) | ||
return nil, "", nil, errors.Wrapf(err, "error computing local image name for %q", transports.ImageName(srcRef)) | ||
} | ||
if destImage == "" { | ||
return nil, nil, errors.Errorf("error computing local image name for %q", transports.ImageName(srcRef)) | ||
return nil, "", nil, errors.Errorf("error computing local image name for %q", transports.ImageName(srcRef)) | ||
} | ||
|
||
ref, err := is.Transport.ParseStoreReference(store, destImage) | ||
if err != nil { | ||
return nil, nil, errors.Wrapf(err, "error parsing reference to image %q", destImage) | ||
return nil, "", nil, errors.Wrapf(err, "error parsing reference to image %q", destImage) | ||
} | ||
img, err := is.Transport.GetStoreImage(store, ref) | ||
if err == nil { | ||
return ref, img, nil | ||
return ref, transport, img, nil | ||
} | ||
|
||
if errors.Cause(err) == storage.ErrImageUnknown && options.PullPolicy != PullIfMissing { | ||
|
@@ -187,26 +187,26 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store | |
continue | ||
} | ||
|
||
pulledImg, pulledReference, err := pullAndFindImage(ctx, store, image, options, systemContext) | ||
pulledImg, pulledReference, err := pullAndFindImage(ctx, store, transport, image, options, systemContext) | ||
if err != nil { | ||
logrus.Debugf("unable to pull and read image %q: %v", image, err) | ||
failures = append(failures, failure{resolvedImageName: image, err: err}) | ||
continue | ||
} | ||
return pulledReference, pulledImg, nil | ||
return pulledReference, transport, pulledImg, nil | ||
} | ||
|
||
if len(failures) != len(candidates) { | ||
return nil, nil, fmt.Errorf("internal error: %d candidates (%#v) vs. %d failures (%#v)", len(candidates), candidates, len(failures), failures) | ||
return nil, "", nil, fmt.Errorf("internal error: %d candidates (%#v) vs. %d failures (%#v)", len(candidates), candidates, len(failures), failures) | ||
} | ||
|
||
registriesConfPath := sysregistries.RegistriesConfPath(systemContext) | ||
switch len(failures) { | ||
case 0: | ||
if searchRegistriesWereUsedButEmpty { | ||
return nil, nil, errors.Errorf("image name %q is a short name and no search registries are defined in %s.", options.FromImage, registriesConfPath) | ||
return nil, "", nil, errors.Errorf("image name %q is a short name and no search registries are defined in %s.", options.FromImage, registriesConfPath) | ||
} | ||
return nil, nil, fmt.Errorf("internal error: no pull candidates were available for %q for an unknown reason", options.FromImage) | ||
return nil, "", nil, fmt.Errorf("internal error: no pull candidates were available for %q for an unknown reason", options.FromImage) | ||
|
||
case 1: | ||
err := failures[0].err | ||
|
@@ -216,15 +216,15 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store | |
if searchRegistriesWereUsedButEmpty { | ||
err = errors.Wrapf(err, "(image name %q is a short name and no search registries are defined in %s)", options.FromImage, registriesConfPath) | ||
} | ||
return nil, nil, err | ||
return nil, "", nil, err | ||
|
||
default: | ||
// NOTE: a multi-line error string: | ||
e := fmt.Sprintf("The following failures happened while trying to pull image specified by %q based on search registries in %s:", options.FromImage, registriesConfPath) | ||
for _, f := range failures { | ||
e = e + fmt.Sprintf("\n* %q: %s", f.resolvedImageName, f.err.Error()) | ||
} | ||
return nil, nil, errors.New(e) | ||
return nil, "", nil, errors.New(e) | ||
} | ||
} | ||
|
||
|
@@ -250,21 +250,19 @@ func findUnusedContainer(name string, containers []storage.Container) string { | |
} | ||
|
||
func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions) (*Builder, error) { | ||
var ref types.ImageReference | ||
var img *storage.Image | ||
var err error | ||
|
||
var ( | ||
ref types.ImageReference | ||
img *storage.Image | ||
err error | ||
) | ||
if options.FromImage == BaseImageFakeName { | ||
options.FromImage = "" | ||
} | ||
if options.Transport == "" { | ||
options.Transport = util.DefaultTransport | ||
} | ||
|
||
systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath) | ||
|
||
if options.FromImage != "" && options.FromImage != "scratch" { | ||
ref, img, err = resolveImage(ctx, systemContext, store, options) | ||
ref, _, img, err = resolveImage(ctx, systemContext, store, options) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering why you switched this to lower case? Also in pull.go. I understand the scoping, but none of the other variables in these structs are lowercase. In some of the code we have a number of variables named transport(s) being used and having this upper case helps it to stand out better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want callers to use this field. We use it to pass the information around withing buildah library, but specifying transport as well as imagename can cause conflicts.
Bottom line, I only want transport derived in one place and from ImageName. Before we had it being derived in different places,and not the same way.