| 
									
										
										
										
											2017-02-11 00:48:15 +08:00
										 |  |  | package buildah | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2018-04-12 22:20:36 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2017-07-29 05:29:37 +08:00
										 |  |  | 	"strings" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-05 21:42:30 +08:00
										 |  |  | 	cp "github.com/containers/image/copy" | 
					
						
							| 
									
										
										
										
											2017-02-14 00:44:47 +08:00
										 |  |  | 	"github.com/containers/image/docker/reference" | 
					
						
							| 
									
										
										
										
											2018-03-19 10:16:47 +08:00
										 |  |  | 	tarfile "github.com/containers/image/docker/tarfile" | 
					
						
							|  |  |  | 	ociarchive "github.com/containers/image/oci/archive" | 
					
						
							| 
									
										
										
										
											2018-06-02 07:33:32 +08:00
										 |  |  | 	"github.com/containers/image/pkg/sysregistries" | 
					
						
							| 
									
										
										
										
											2017-02-11 00:48:15 +08:00
										 |  |  | 	"github.com/containers/image/signature" | 
					
						
							|  |  |  | 	is "github.com/containers/image/storage" | 
					
						
							| 
									
										
										
										
											2017-07-29 05:29:37 +08:00
										 |  |  | 	"github.com/containers/image/transports" | 
					
						
							| 
									
										
										
										
											2017-03-22 04:38:50 +08:00
										 |  |  | 	"github.com/containers/image/transports/alltransports" | 
					
						
							| 
									
										
										
										
											2017-02-11 00:48:15 +08:00
										 |  |  | 	"github.com/containers/image/types" | 
					
						
							| 
									
										
										
										
											2017-05-17 23:53:28 +08:00
										 |  |  | 	"github.com/containers/storage" | 
					
						
							| 
									
										
										
										
											2017-06-02 03:23:02 +08:00
										 |  |  | 	"github.com/pkg/errors" | 
					
						
							| 
									
										
										
										
											2018-03-19 10:16:47 +08:00
										 |  |  | 	"github.com/projectatomic/buildah/util" | 
					
						
							| 
									
										
										
										
											2017-10-10 03:05:56 +08:00
										 |  |  | 	"github.com/sirupsen/logrus" | 
					
						
							| 
									
										
										
										
											2017-02-11 00:48:15 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 22:20:36 +08:00
										 |  |  | func localImageNameForReference(ctx context.Context, store storage.Store, srcRef types.ImageReference, spec string) (string, error) { | 
					
						
							| 
									
										
										
										
											2017-07-29 05:29:37 +08:00
										 |  |  | 	if srcRef == nil { | 
					
						
							|  |  |  | 		return "", errors.Errorf("reference to image is empty") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-19 10:16:47 +08:00
										 |  |  | 	split := strings.SplitN(spec, ":", 2) | 
					
						
							|  |  |  | 	file := split[len(split)-1] | 
					
						
							|  |  |  | 	var name string | 
					
						
							|  |  |  | 	switch srcRef.Transport().Name() { | 
					
						
							|  |  |  | 	case util.DockerArchive: | 
					
						
							|  |  |  | 		tarSource, err := tarfile.NewSourceFromFile(file) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return "", err | 
					
						
							| 
									
										
										
										
											2017-07-29 05:29:37 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-19 10:16:47 +08:00
										 |  |  | 		manifest, err := tarSource.LoadTarManifest() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return "", errors.Errorf("error retrieving manifest.json: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// to pull the first image stored in the tar file
 | 
					
						
							|  |  |  | 		if len(manifest) == 0 { | 
					
						
							|  |  |  | 			// use the hex of the digest if no manifest is found
 | 
					
						
							| 
									
										
										
										
											2018-04-12 22:20:36 +08:00
										 |  |  | 			name, err = getImageDigest(ctx, srcRef, nil) | 
					
						
							| 
									
										
										
										
											2018-03-19 10:16:47 +08:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return "", err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			if len(manifest[0].RepoTags) > 0 { | 
					
						
							|  |  |  | 				name = manifest[0].RepoTags[0] | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				// If the input image has no repotags, we need to feed it a dest anyways
 | 
					
						
							| 
									
										
										
										
											2018-04-12 22:20:36 +08:00
										 |  |  | 				name, err = getImageDigest(ctx, srcRef, nil) | 
					
						
							| 
									
										
										
										
											2018-03-19 10:16:47 +08:00
										 |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					return "", err | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case util.OCIArchive: | 
					
						
							|  |  |  | 		// retrieve the manifest from index.json to access the image name
 | 
					
						
							|  |  |  | 		manifest, err := ociarchive.LoadManifestDescriptor(srcRef) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return "", errors.Wrapf(err, "error loading manifest for %q", srcRef) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-05-17 00:38:11 +08:00
										 |  |  | 		// if index.json has no reference name, compute the image digest instead
 | 
					
						
							| 
									
										
										
										
											2018-03-19 10:16:47 +08:00
										 |  |  | 		if manifest.Annotations == nil || manifest.Annotations["org.opencontainers.image.ref.name"] == "" { | 
					
						
							| 
									
										
										
										
											2018-05-17 00:38:11 +08:00
										 |  |  | 			name, err = getImageDigest(ctx, srcRef, nil) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return "", err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			name = manifest.Annotations["org.opencontainers.image.ref.name"] | 
					
						
							| 
									
										
										
										
											2018-03-19 10:16:47 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	case util.DirTransport: | 
					
						
							|  |  |  | 		// supports pull from a directory
 | 
					
						
							|  |  |  | 		name = split[1] | 
					
						
							|  |  |  | 		// remove leading "/"
 | 
					
						
							|  |  |  | 		if name[:1] == "/" { | 
					
						
							|  |  |  | 			name = name[1:] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		ref := srcRef.DockerReference() | 
					
						
							|  |  |  | 		if ref == nil { | 
					
						
							| 
									
										
										
										
											2018-04-19 16:52:24 +08:00
										 |  |  | 			name = srcRef.StringWithinTransport() | 
					
						
							| 
									
										
										
										
											2018-03-19 10:16:47 +08:00
										 |  |  | 			_, err := is.Transport.ParseStoreReference(store, name) | 
					
						
							| 
									
										
										
										
											2017-07-29 05:29:37 +08:00
										 |  |  | 			if err == nil { | 
					
						
							|  |  |  | 				return name, nil | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-03-19 10:16:47 +08:00
										 |  |  | 			if strings.LastIndex(name, "/") != -1 { | 
					
						
							|  |  |  | 				name = name[strings.LastIndex(name, "/")+1:] | 
					
						
							|  |  |  | 				_, err = is.Transport.ParseStoreReference(store, name) | 
					
						
							|  |  |  | 				if err == nil { | 
					
						
							|  |  |  | 					return name, nil | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return "", errors.Errorf("reference to image %q is not a named reference", transports.ImageName(srcRef)) | 
					
						
							| 
									
										
										
										
											2017-07-29 05:29:37 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-19 10:16:47 +08:00
										 |  |  | 		if named, ok := ref.(reference.Named); ok { | 
					
						
							|  |  |  | 			name = named.Name() | 
					
						
							|  |  |  | 			if namedTagged, ok := ref.(reference.NamedTagged); ok { | 
					
						
							|  |  |  | 				name = name + ":" + namedTagged.Tag() | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if canonical, ok := ref.(reference.Canonical); ok { | 
					
						
							|  |  |  | 				name = name + "@" + canonical.Digest().String() | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-07-29 05:29:37 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if _, err := is.Transport.ParseStoreReference(store, name); err != nil { | 
					
						
							|  |  |  | 		return "", errors.Wrapf(err, "error parsing computed local image name %q", name) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return name, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 22:20:36 +08:00
										 |  |  | func pullImage(ctx context.Context, store storage.Store, imageName string, options BuilderOptions, sc *types.SystemContext) (types.ImageReference, error) { | 
					
						
							| 
									
										
										
										
											2017-06-29 05:07:58 +08:00
										 |  |  | 	spec := imageName | 
					
						
							|  |  |  | 	srcRef, err := alltransports.ParseImageName(spec) | 
					
						
							| 
									
										
										
										
											2017-02-11 00:48:15 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-06-29 05:07:58 +08:00
										 |  |  | 		if options.Transport == "" { | 
					
						
							|  |  |  | 			return nil, errors.Wrapf(err, "error parsing image name %q", spec) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-19 10:16:47 +08:00
										 |  |  | 		transport := options.Transport | 
					
						
							|  |  |  | 		if transport != DefaultTransport { | 
					
						
							|  |  |  | 			transport = transport + ":" | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		spec = transport + spec | 
					
						
							| 
									
										
										
										
											2017-03-22 04:38:50 +08:00
										 |  |  | 		srcRef2, err2 := alltransports.ParseImageName(spec) | 
					
						
							| 
									
										
										
										
											2017-02-11 00:48:15 +08:00
										 |  |  | 		if err2 != nil { | 
					
						
							| 
									
										
										
										
											2017-06-29 05:07:58 +08:00
										 |  |  | 			return nil, errors.Wrapf(err2, "error parsing image name %q", spec) | 
					
						
							| 
									
										
										
										
											2017-02-11 00:48:15 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		srcRef = srcRef2 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 22:20:36 +08:00
										 |  |  | 	destName, err := localImageNameForReference(ctx, store, srcRef, spec) | 
					
						
							| 
									
										
										
										
											2017-07-29 05:29:37 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, errors.Wrapf(err, "error computing local image name for %q", transports.ImageName(srcRef)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if destName == "" { | 
					
						
							|  |  |  | 		return nil, errors.Errorf("error computing local image name for %q", transports.ImageName(srcRef)) | 
					
						
							| 
									
										
										
										
											2017-02-11 00:48:15 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-29 05:29:37 +08:00
										 |  |  | 	destRef, err := is.Transport.ParseStoreReference(store, destName) | 
					
						
							| 
									
										
										
										
											2017-02-11 00:48:15 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-07-29 05:29:37 +08:00
										 |  |  | 		return nil, errors.Wrapf(err, "error parsing image name %q", destName) | 
					
						
							| 
									
										
										
										
											2017-02-11 00:48:15 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 22:20:36 +08:00
										 |  |  | 	img, err := srcRef.NewImageSource(ctx, sc) | 
					
						
							| 
									
										
										
										
											2017-06-29 05:07:58 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, errors.Wrapf(err, "error initializing %q as an image source", spec) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	img.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-11 00:48:15 +08:00
										 |  |  | 	policy, err := signature.DefaultPolicy(sc) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-07-29 05:29:37 +08:00
										 |  |  | 		return nil, errors.Wrapf(err, "error obtaining default signature policy") | 
					
						
							| 
									
										
										
										
											2017-02-11 00:48:15 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	policyContext, err := signature.NewPolicyContext(policy) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-07-29 05:29:37 +08:00
										 |  |  | 		return nil, errors.Wrapf(err, "error creating new signature policy context") | 
					
						
							| 
									
										
										
										
											2017-02-11 00:48:15 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-29 00:58:29 +08:00
										 |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if err2 := policyContext.Destroy(); err2 != nil { | 
					
						
							| 
									
										
										
										
											2017-06-29 05:07:58 +08:00
										 |  |  | 			logrus.Debugf("error destroying signature policy context: %v", err2) | 
					
						
							| 
									
										
										
										
											2017-07-29 00:58:29 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-29 05:07:58 +08:00
										 |  |  | 	logrus.Debugf("copying %q to %q", spec, destName) | 
					
						
							| 
									
										
										
										
											2018-04-12 22:20:36 +08:00
										 |  |  | 	err = cp.Image(ctx, policyContext, destRef, srcRef, getCopyOptions(options.ReportWriter, options.SystemContext, nil, "")) | 
					
						
							| 
									
										
										
										
											2017-06-29 05:07:58 +08:00
										 |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		return destRef, nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-06-02 07:33:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// If no image was found, we should handle.  Lets be nicer to the user and see if we can figure out why.
 | 
					
						
							|  |  |  | 	registryPath := sysregistries.RegistriesConfPath(&types.SystemContext{}) | 
					
						
							|  |  |  | 	searchRegistries, err := getRegistries() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	hasRegistryInName, err := hasRegistry(imageName) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !hasRegistryInName && len(searchRegistries) == 0 { | 
					
						
							|  |  |  | 		return nil, errors.Errorf("image name provided is a short name and no search registries are defined in %s.", registryPath) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil, errors.Errorf("unable to find image in the registries defined in %q", registryPath) | 
					
						
							| 
									
										
										
										
											2017-02-11 00:48:15 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-19 10:16:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // getImageDigest creates an image object and uses the hex value of the digest as the image ID
 | 
					
						
							|  |  |  | // for parsing the store reference
 | 
					
						
							| 
									
										
										
										
											2018-04-12 22:20:36 +08:00
										 |  |  | func getImageDigest(ctx context.Context, src types.ImageReference, sc *types.SystemContext) (string, error) { | 
					
						
							|  |  |  | 	newImg, err := src.NewImage(ctx, sc) | 
					
						
							| 
									
										
										
										
											2018-03-19 10:16:47 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return "", err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer newImg.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	digest := newImg.ConfigInfo().Digest | 
					
						
							|  |  |  | 	if err = digest.Validate(); err != nil { | 
					
						
							|  |  |  | 		return "", errors.Wrapf(err, "error getting config info") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return "@" + digest.Hex(), nil | 
					
						
							|  |  |  | } |