diff options
author | umohnani8 <umohnani@redhat.com> | 2018-05-21 13:53:19 -0400 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2018-05-25 15:15:47 +0000 |
commit | c8b72e57a75262c0edeea839e9e34bb0c3e03d13 (patch) | |
tree | 3a2bb7210d309e358bfe84a0ab0f60e57b9f2e2f /libpod | |
parent | 0a4ade1c175d3188ad55d22d751a86c96e060a44 (diff) | |
download | podman-c8b72e57a75262c0edeea839e9e34bb0c3e03d13.tar.gz podman-c8b72e57a75262c0edeea839e9e34bb0c3e03d13.tar.bz2 podman-c8b72e57a75262c0edeea839e9e34bb0c3e03d13.zip |
save and load should support multi-tag for docker-archive
The docker-archive tar files can have multiple tags for the same
image stored in it. Load pulls all the tags found in the archive
when loading a tar file. Save can oush multiple tags of the same
image to a tar archive.
Signed-off-by: umohnani8 <umohnani@redhat.com>
Closes: #819
Approved by: rhatdan
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/image/docker_registry_options.go | 8 | ||||
-rw-r--r-- | libpod/image/image.go | 43 | ||||
-rw-r--r-- | libpod/image/pull.go | 41 | ||||
-rw-r--r-- | libpod/image/utils.go | 23 |
4 files changed, 89 insertions, 26 deletions
diff --git a/libpod/image/docker_registry_options.go b/libpod/image/docker_registry_options.go index bbb49df28..838edf2d0 100644 --- a/libpod/image/docker_registry_options.go +++ b/libpod/image/docker_registry_options.go @@ -1,6 +1,9 @@ package image -import "github.com/containers/image/types" +import ( + "github.com/containers/image/docker/reference" + "github.com/containers/image/types" +) // DockerRegistryOptions encapsulates settings that affect how we connect or // authenticate to a remote registry. @@ -22,7 +25,7 @@ type DockerRegistryOptions struct { // GetSystemContext constructs a new system context from the given signaturePolicy path and the // values in the DockerRegistryOptions -func (o DockerRegistryOptions) GetSystemContext(signaturePolicyPath, authFile string, forceCompress bool) *types.SystemContext { +func (o DockerRegistryOptions) GetSystemContext(signaturePolicyPath, authFile string, forceCompress bool, additionalDockerArchiveTags []reference.NamedTagged) *types.SystemContext { sc := &types.SystemContext{ SignaturePolicyPath: signaturePolicyPath, DockerAuthConfig: o.DockerRegistryCreds, @@ -30,6 +33,7 @@ func (o DockerRegistryOptions) GetSystemContext(signaturePolicyPath, authFile st DockerInsecureSkipTLSVerify: o.DockerInsecureSkipTLSVerify, AuthFilePath: authFile, DirForceCompress: forceCompress, + DockerArchiveAdditionalTags: additionalDockerArchiveTags, } return sc } diff --git a/libpod/image/image.go b/libpod/image/image.go index b7d9200ec..c8a929074 100644 --- a/libpod/image/image.go +++ b/libpod/image/image.go @@ -147,7 +147,7 @@ func (ir *Runtime) New(ctx context.Context, name, signaturePolicyPath, authfile return nil, errors.Wrapf(err, "unable to pull %s", name) } - newImage.InputName = imageName + newImage.InputName = imageName[0] img, err := newImage.getLocalImage() if err != nil { return nil, errors.Wrapf(err, "error retrieving local image after pulling %s", name) @@ -156,6 +156,41 @@ func (ir *Runtime) New(ctx context.Context, name, signaturePolicyPath, authfile return &newImage, nil } +// LoadFromArchive creates a new image object for images pulled from a tar archive (podman load) +// This function is needed because it is possible for a tar archive to have multiple tags for one image +func (ir *Runtime) LoadFromArchive(ctx context.Context, name, signaturePolicyPath string, writer io.Writer) ([]*Image, error) { + var newImages []*Image + newImage := Image{ + InputName: name, + Local: false, + imageruntime: ir, + } + + if signaturePolicyPath == "" { + signaturePolicyPath = ir.SignaturePolicyPath + } + imageNames, err := newImage.pullImage(ctx, writer, "", signaturePolicyPath, SigningOptions{}, &DockerRegistryOptions{}, false) + if err != nil { + return nil, errors.Wrapf(err, "unable to pull %s", name) + } + + for _, name := range imageNames { + newImage := Image{ + InputName: name, + Local: true, + imageruntime: ir, + } + img, err := newImage.getLocalImage() + if err != nil { + return nil, errors.Wrapf(err, "error retrieving local image after pulling %s", name) + } + newImage.image = img + newImages = append(newImages, &newImage) + } + + return newImages, nil +} + // Shutdown closes down the storage and require a bool arg as to // whether it should do so forcibly. func (ir *Runtime) Shutdown(force bool) error { @@ -428,7 +463,7 @@ func (i *Image) UntagImage(tag string) error { } // PushImage pushes the given image to a location described by the given path -func (i *Image) PushImage(ctx context.Context, destination, manifestMIMEType, authFile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions SigningOptions, dockerRegistryOptions *DockerRegistryOptions, forceSecure bool) error { +func (i *Image) PushImage(ctx context.Context, destination, manifestMIMEType, authFile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions SigningOptions, dockerRegistryOptions *DockerRegistryOptions, forceSecure bool, additionalDockerArchiveTags []reference.NamedTagged) error { if destination == "" { return errors.Wrapf(syscall.EINVAL, "destination image name must be specified") } @@ -464,7 +499,7 @@ func (i *Image) PushImage(ctx context.Context, destination, manifestMIMEType, au if err != nil { return err } - copyOptions := getCopyOptions(writer, signaturePolicyPath, nil, dockerRegistryOptions, signingOptions, authFile, manifestMIMEType, forceCompress) + copyOptions := getCopyOptions(writer, signaturePolicyPath, nil, dockerRegistryOptions, signingOptions, authFile, manifestMIMEType, forceCompress, additionalDockerArchiveTags) if strings.HasPrefix(DockerTransport, dest.Transport().Name()) { imgRef, err := reference.Parse(dest.DockerReference().String()) if err != nil { @@ -749,7 +784,7 @@ func (ir *Runtime) Import(ctx context.Context, path, reference string, writer io return nil, err } defer policyContext.Destroy() - copyOptions := getCopyOptions(writer, "", nil, nil, signingOptions, "", "", false) + copyOptions := getCopyOptions(writer, "", nil, nil, signingOptions, "", "", false, nil) dest, err := is.Transport.ParseStoreReference(ir.store, reference) if err != nil { errors.Wrapf(err, "error getting image reference for %q", reference) diff --git a/libpod/image/pull.go b/libpod/image/pull.go index 38a8435de..cd915cb47 100644 --- a/libpod/image/pull.go +++ b/libpod/image/pull.go @@ -100,21 +100,25 @@ func (ir *Runtime) getPullListFromRef(ctx context.Context, srcRef types.ImageRef } pullStructs = append(pullStructs, pullInfo) } else { - var dest string + var dest []string if len(manifest[0].RepoTags) > 0 { - dest = manifest[0].RepoTags[0] + dest = append(dest, manifest[0].RepoTags...) } else { // If the input image has no repotags, we need to feed it a dest anyways - dest, err = getImageDigest(ctx, srcRef, sc) + digest, err := getImageDigest(ctx, srcRef, sc) if err != nil { return nil, err } + dest = append(dest, digest) } - pullInfo, err := ir.getPullStruct(srcRef, dest) - if err != nil { - return nil, err + // Need to load in all the repo tags from the manifest + for _, dst := range dest { + pullInfo, err := ir.getPullStruct(srcRef, dst) + if err != nil { + return nil, err + } + pullStructs = append(pullStructs, pullInfo) } - pullStructs = append(pullStructs, pullInfo) } } else if srcRef.Transport().Name() == OCIArchive { // retrieve the manifest from index.json to access the image name @@ -164,7 +168,7 @@ func (ir *Runtime) getPullListFromRef(ctx context.Context, srcRef types.ImageRef // pullImage pulls an image from configured registries // By default, only the latest tag (or a specific tag if requested) will be // pulled. -func (i *Image) pullImage(ctx context.Context, writer io.Writer, authfile, signaturePolicyPath string, signingOptions SigningOptions, dockerOptions *DockerRegistryOptions, forceSecure bool) (string, error) { +func (i *Image) pullImage(ctx context.Context, writer io.Writer, authfile, signaturePolicyPath string, signingOptions SigningOptions, dockerOptions *DockerRegistryOptions, forceSecure bool) ([]string, error) { // pullImage copies the image from the source to the destination var pullStructs []*pullStruct sc := GetSystemContext(signaturePolicyPath, authfile, false) @@ -173,31 +177,31 @@ func (i *Image) pullImage(ctx context.Context, writer io.Writer, authfile, signa // could be trying to pull from registry with short name pullStructs, err = i.createNamesToPull() if err != nil { - return "", errors.Wrap(err, "error getting default registries to try") + return nil, errors.Wrap(err, "error getting default registries to try") } } else { pullStructs, err = i.imageruntime.getPullListFromRef(ctx, srcRef, i.InputName, sc) if err != nil { - return "", errors.Wrapf(err, "error getting pullStruct info to pull image %q", i.InputName) + return nil, errors.Wrapf(err, "error getting pullStruct info to pull image %q", i.InputName) } } policyContext, err := getPolicyContext(sc) if err != nil { - return "", err + return nil, err } defer policyContext.Destroy() insecureRegistries, err := registries.GetInsecureRegistries() if err != nil { - return "", err + return nil, err } - + var images []string for _, imageInfo := range pullStructs { - copyOptions := getCopyOptions(writer, signaturePolicyPath, dockerOptions, nil, signingOptions, authfile, "", false) + copyOptions := getCopyOptions(writer, signaturePolicyPath, dockerOptions, nil, signingOptions, authfile, "", false, nil) if strings.HasPrefix(DockerTransport, imageInfo.srcRef.Transport().Name()) { imgRef, err := reference.Parse(imageInfo.srcRef.DockerReference().String()) if err != nil { - return "", err + return nil, err } registry := reference.Domain(imgRef.(reference.Named)) @@ -215,10 +219,13 @@ func (i *Image) pullImage(ctx context.Context, writer io.Writer, authfile, signa io.WriteString(writer, "Failed\n") } } else { - return imageInfo.image, nil + if imageInfo.srcRef.Transport().Name() != DockerArchive { + return []string{imageInfo.image}, nil + } + images = append(images, imageInfo.image) } } - return "", errors.Wrapf(err, "error pulling image from") + return images, errors.Wrapf(err, "error pulling image from") } // createNamesToPull looks at a decomposed image and determines the possible diff --git a/libpod/image/utils.go b/libpod/image/utils.go index 5392b86f0..661fece07 100644 --- a/libpod/image/utils.go +++ b/libpod/image/utils.go @@ -53,15 +53,15 @@ func findImageInRepotags(search imageParts, images []*Image) (*storage.Image, er } // getCopyOptions constructs a new containers/image/copy.Options{} struct from the given parameters -func getCopyOptions(reportWriter io.Writer, signaturePolicyPath string, srcDockerRegistry, destDockerRegistry *DockerRegistryOptions, signing SigningOptions, authFile, manifestType string, forceCompress bool) *cp.Options { +func getCopyOptions(reportWriter io.Writer, signaturePolicyPath string, srcDockerRegistry, destDockerRegistry *DockerRegistryOptions, signing SigningOptions, authFile, manifestType string, forceCompress bool, additionalDockerArchiveTags []reference.NamedTagged) *cp.Options { if srcDockerRegistry == nil { srcDockerRegistry = &DockerRegistryOptions{} } if destDockerRegistry == nil { destDockerRegistry = &DockerRegistryOptions{} } - srcContext := srcDockerRegistry.GetSystemContext(signaturePolicyPath, authFile, forceCompress) - destContext := destDockerRegistry.GetSystemContext(signaturePolicyPath, authFile, forceCompress) + srcContext := srcDockerRegistry.GetSystemContext(signaturePolicyPath, authFile, forceCompress, additionalDockerArchiveTags) + destContext := destDockerRegistry.GetSystemContext(signaturePolicyPath, authFile, forceCompress, additionalDockerArchiveTags) return &cp.Options{ RemoveSignatures: signing.RemoveSignatures, SignBy: signing.SignBy, @@ -110,3 +110,20 @@ func ReposToMap(repotags []string) map[string][]string { } return repos } + +// GetAdditionalTags returns a list of reference.NamedTagged for the +// additional tags given in images +func GetAdditionalTags(images []string) ([]reference.NamedTagged, error) { + var allTags []reference.NamedTagged + for _, img := range images { + ref, err := reference.ParseNormalizedNamed(img) + if err != nil { + return nil, errors.Wrapf(err, "error parsing additional tags") + } + refTagged, isTagged := ref.(reference.NamedTagged) + if isTagged { + allTags = append(allTags, refTagged) + } + } + return allTags, nil +} |