Skip to content

Commit

Permalink
WIP - load/save: support multi-image archives
Browse files Browse the repository at this point in the history
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
  • Loading branch information
vrothberg committed Jul 2, 2020
1 parent 9fb0b56 commit 9efd4e8
Show file tree
Hide file tree
Showing 23 changed files with 787 additions and 333 deletions.
2 changes: 1 addition & 1 deletion cmd/podman/images/save.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func saveFlags(flags *pflag.FlagSet) {
flags.StringVar(&saveOpts.Format, "format", define.V2s2Archive, "Save image to oci-archive, oci-dir (directory with oci manifest type), docker-archive, docker-dir (directory with v2s2 manifest type)")
flags.StringVarP(&saveOpts.Output, "output", "o", "", "Write to a specified file (default: stdout, which must be redirected)")
flags.BoolVarP(&saveOpts.Quiet, "quiet", "q", false, "Suppress the output")

flags.BoolVarP(&saveOpts.MultiImageArchive, "multi-image-archive", "m", false, "Interpret additional arguments as images not tags and create a multi-image-archive")
}

func save(cmd *cobra.Command, args []string) error {
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,5 @@ require (
k8s.io/apimachinery v0.18.5
k8s.io/client-go v0.0.0-20190620085101-78d2af792bab
)

replace github.com/containers/image/v5 => /home/valentin/containers/image
16 changes: 2 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,12 @@ github.com/containers/common v0.15.1 h1:ycIJf7ugHf0f2ag9uYFijQLbcrPu1KnOqdARgs2X
github.com/containers/common v0.15.1/go.mod h1:zJ/BLqK6INqFOCxN/gh9ae1qqWD/ghk2T0jAYqz/Xq4=
github.com/containers/conmon v2.0.18+incompatible h1:rjwjNnE756NuXcdE/uUmj4kDbrykslPuBMHI31wh43E=
github.com/containers/conmon v2.0.18+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.4.4/go.mod h1:g7cxNXitiLi6pEr9/L9n/0wfazRuhDKXU15kV86N8h8=
github.com/containers/image/v5 v5.5.1 h1:h1FCOXH6Ux9/p/E4rndsQOC4yAdRU0msRTfLVeQ7FDQ=
github.com/containers/image/v5 v5.5.1/go.mod h1:4PyNYR0nwlGq/ybVJD9hWlhmIsNra4Q8uOQX2s6E2uM=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/ocicrypt v1.0.2 h1:Q0/IPs8ohfbXNxEfyJ2pFVmvJu5BhqJUAmc6ES9NKbo=
github.com/containers/ocicrypt v1.0.2/go.mod h1:nsOhbP19flrX6rE7ieGFvBlr7modwmNjsqWarIUce4M=
github.com/containers/psgo v1.5.1 h1:MQNb7FLbXqBdqz6u4lI2QWizVz4RSTzs1+Nk9XT1iVA=
github.com/containers/psgo v1.5.1/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzPUWfawVU=
github.com/containers/storage v1.19.1/go.mod h1:KbXjSwKnx17ejOsjFcCXSf78mCgZkQSLPBNTMRc3XrQ=
github.com/containers/storage v1.20.2 h1:tw/uKRPDnmVrluIzer3dawTFG/bTJLP8IEUyHFhltYk=
github.com/containers/storage v1.20.2/go.mod h1:oOB9Ie8OVPojvoaKWEGSEtHbXUAs+tSyr7RO7ZGteMc=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
Expand Down Expand Up @@ -248,11 +244,9 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.10.5/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.10.8 h1:eLeJ3dr/Y9+XRfJT4l+8ZjmtB5RPJhucH2HeCV5+IZY=
github.com/klauspost/compress v1.10.8/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/pgzip v1.2.3/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/klauspost/compress v1.10.10 h1:a/y8CglcM7gLGYmlbP/stPE5sR3hbhFRUjCBfd/0B3I=
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/pgzip v1.2.4 h1:TQ7CNpYKovDOmqzRHKxJh0BeaBI7UdQZYc6p7pMQh1A=
github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
Expand Down Expand Up @@ -327,7 +321,6 @@ github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6/go.mod
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v0.0.0-20190425234816-dae70e8efea4/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc90 h1:4+xo8mtWixbHoEm451+WJNUrq12o2/tDsyK9Vgc/NcA=
github.com/opencontainers/runc v1.0.0-rc90/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
Expand All @@ -338,7 +331,6 @@ github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mo
github.com/opencontainers/runtime-tools v0.9.0 h1:FYgwVsKRI/H9hU32MJ/4MLOzXWodKK5zsQavY8NPMkU=
github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
github.com/opencontainers/selinux v1.3.0/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs=
github.com/opencontainers/selinux v1.5.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
github.com/opencontainers/selinux v1.5.2 h1:F6DgIsjgBIcDksLW4D5RG9bXok6oqZ3nvMwj4ZoFu/Q=
github.com/opencontainers/selinux v1.5.2/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
github.com/openshift/imagebuilder v1.1.5 h1:WAIHV6cGF9e0AcLBA7RIi7XbFoB7R+e/MWu1I+1NUOM=
Expand Down Expand Up @@ -446,7 +438,6 @@ github.com/varlink/go v0.0.0-20190502142041-0f1d566d194b h1:hdDRrn9OP/roL8a/e/5Z
github.com/varlink/go v0.0.0-20190502142041-0f1d566d194b/go.mod h1:YHaw8N660ESgMgLOZfLQqT1htFItynAUxMesFBho52s=
github.com/vbatts/tar-split v0.11.1 h1:0Odu65rhcZ3JZaPHxl7tCI3V/C/Q9Zf82UFravl02dE=
github.com/vbatts/tar-split v0.11.1/go.mod h1:LEuURwDEiWjRjwu46yU3KVGuUdVv/dcnpcEPSzR8z6g=
github.com/vbauerster/mpb/v5 v5.0.4/go.mod h1:fvzasBUyuo35UyuA6sSOlVhpLoNQsp2nBdHw7OiSUU8=
github.com/vbauerster/mpb/v5 v5.2.2 h1:zIICVOm+XD+uV6crpSORaL6I0Q1WqOdvxZTp+r3L9cw=
github.com/vbauerster/mpb/v5 v5.2.2/go.mod h1:W5Fvgw4dm3/0NhqzV8j6EacfuTe5SvnzBRwiXxDR9ww=
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
Expand Down Expand Up @@ -503,7 +494,6 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
Expand Down Expand Up @@ -542,12 +532,10 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
161 changes: 158 additions & 3 deletions libpod/image/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (

cp "github.com/containers/image/v5/copy"
"github.com/containers/image/v5/directory"
"github.com/containers/image/v5/docker/archive"
dockerarchive "github.com/containers/image/v5/docker/archive"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/image"
Expand Down Expand Up @@ -169,15 +170,169 @@ func (ir *Runtime) New(ctx context.Context, name, signaturePolicyPath, authfile
return newImage, nil
}

// SaveImages stores one more images in a multi-image archive.
// Note that only `docker-archive` supports storing multiple
// image.
func (ir *Runtime) SaveImages(ctx context.Context, namesOrIDs []string, format string, outputFile string, quiet bool) (finalErr error) {
if format != DockerArchive {
return errors.Errorf("multi-image archives are only supported in in the %q format", DockerArchive)
}

sys := GetSystemContext("", "", false)
multiDest, err := archive.NewMultiImageDestination(sys, outputFile)
if err != nil {
return err
}

policyContext, err := getPolicyContext(sys)
if err != nil {
return err
}
defer func() {
if err := policyContext.Destroy(); err != nil {
logrus.Errorf("failed to destroy policy context: %q", err)
}
if err := multiDest.Finalize(ctx); err != nil {
if finalErr == nil {
finalErr = err
} else {
finalErr = errors.Wrap(finalErr, err.Error())
}
}
}()

manifestMIMEType := multiDest.SupportedManifestMIMETypes()[0]

// Check whether c/image's progress bars use stderr or stdout. Use
// stderr in case we need to be quiet or if the output is set to
// stdout. If the output is set of stout, any log message there would
// corrupt the tarfile.
writer := os.Stdout
if quiet || outputFile == os.Stdout.Name() {
writer = os.Stderr
}

// Look up the images in the local storage and determine the tags for
// them.
imageTags := make(map[*Image][]string)
imageOrder := []*Image{}
for _, nameOrID := range namesOrIDs {
// Look up the name or ID in the local image storage.
localImage, err := ir.NewFromLocal(nameOrID)
if err != nil {
return err
}

tags, exists := imageTags[localImage]
if !exists {
// Preserve the relative order AND make the archives
// deterministic - iterating over go maps yields a
// random order.
imageOrder = append(imageOrder, localImage)
}

// Unless we referred to an ID, add the input as a tag.
id := localImage.ID()
if strings.HasPrefix(id, nameOrID) {
continue
}
tag, err := NormalizedTag(nameOrID)
if err != nil {
return err
}
tags = append(tags, tag.String())
imageTags[localImage] = tags
}

// Now copy the images one-by-one.
copyOptions := getCopyOptions(sys, writer, nil, nil, SigningOptions{}, manifestMIMEType, nil)
copyOptions.DestinationCtx.SystemRegistriesConfPath = registries.SystemRegistriesConfPath()
for _, img := range imageOrder {
unparsedTags, _ := imageTags[img]
logrus.Errorf("Saving image: %q", img.ID())
logrus.Errorf("Tags: %v", unparsedTags)

tags, err := GetAdditionalTags(unparsedTags)
if err != nil {
return err
}
multiDest.AddRepoTags(tags)

// For copying, we need a source reference that we can create
// from the image.
src, err := is.Transport.ParseStoreReference(img.imageruntime.store, img.ID())
if err != nil {
return errors.Wrapf(err, "error getting source imageReference for %q", img.InputName)
}

_, err = cp.Image(ctx, policyContext, multiDest.Reference(), src, copyOptions)
if err != nil {
return err
}
}

return nil
}

func (ir *Runtime) loadMultiImageArchive(ctx context.Context, sys *types.SystemContext, ref types.ImageReference, writer io.Writer) ([]string, error) {
if ref.Transport().Name() != DockerArchive {
return nil, errors.Errorf("wrong transport %q: only %q supports multi-image archives", ref, DockerArchive)
}

multiSource, err := archive.NewMultiImageSource(ctx, sys, ref.StringWithinTransport())
if err != nil {
return nil, err
}
defer multiSource.Close()

items, err := multiSource.Items()
if err != nil {
return nil, err
}

var loadedImages []string
for _, item := range items {
manifest, err := item.Manifest()
if err != nil {
return nil, errors.Wrapf(err, "error retrieving manifest")
}
goal, err := ir.pullGoalFromTarManifest(ctx, manifest, item, sys)
if err != nil {
return nil, err
}
imageNames, err := ir.doPullImage(ctx, sys, *goal, writer, SigningOptions{}, &DockerRegistryOptions{}, nil)
if err != nil {
return nil, err
}

loadedImages = append(loadedImages, imageNames...)
}

return loadedImages, nil
}

// LoadFromArchiveReference creates a new image object for images pulled from a tar archive and the like (podman load)
// This function is needed because it is possible for a tar archive to have multiple tags for one image
func (ir *Runtime) LoadFromArchiveReference(ctx context.Context, srcRef types.ImageReference, signaturePolicyPath string, writer io.Writer) ([]*Image, error) {
if signaturePolicyPath == "" {
signaturePolicyPath = ir.SignaturePolicyPath
}
imageNames, err := ir.pullImageFromReference(ctx, srcRef, writer, "", signaturePolicyPath, SigningOptions{}, &DockerRegistryOptions{})
if err != nil {
return nil, errors.Wrapf(err, "unable to pull %s", transports.ImageName(srcRef))

var imageNames []string
var err error

switch srcRef.Transport().Name() {
case DockerArchive:
sys := GetSystemContext(signaturePolicyPath, "", false)
imageNames, err = ir.loadMultiImageArchive(ctx, sys, srcRef, writer)
if err != nil {
return nil, errors.Wrapf(err, "unable to load %s", transports.ImageName(srcRef))
}
default:
imageNames, err = ir.pullImageFromReference(ctx, srcRef, writer, "", signaturePolicyPath, SigningOptions{}, &DockerRegistryOptions{})
if err != nil {
return nil, errors.Wrapf(err, "unable to pull %s", transports.ImageName(srcRef))
}
}

newImages := make([]*Image, 0, len(imageNames))
Expand Down
95 changes: 52 additions & 43 deletions libpod/image/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,52 @@ func (ir *Runtime) getSinglePullRefPairGoal(srcRef types.ImageReference, destNam
return singlePullRefPairGoal(rp), nil
}

// pullGoalFromTarManifest creates a pull goal based on the specified
// ManifestItem slice. If present, the goal will be generated based on the
// first item in the slice.
func (ir *Runtime) pullGoalFromTarManifest(ctx context.Context, manifest *tarfile.ManifestItem, srcRef types.ImageReference, sc *types.SystemContext) (*pullGoal, error) {
if manifest == nil {
// use the hex of the digest if no manifest is found
reference, err := getImageDigest(ctx, srcRef, sc)
if err != nil {
return nil, err
}
return ir.getSinglePullRefPairGoal(srcRef, reference)
}

if len(manifest.RepoTags) == 0 {
// If the input image has no repotags, we need to feed it a dest anyways
digest, err := getImageDigest(ctx, srcRef, sc)
if err != nil {
return nil, err
}
return ir.getSinglePullRefPairGoal(srcRef, digest)
}

// Need to load in all the repo tags from the manifest
res := []pullRefPair{}
for _, dst := range manifest.RepoTags {
// Check if image exists and give a warning of untagging
localImage, err := ir.NewFromLocal(dst)
imageID := strings.TrimSuffix(manifest.Config, ".json")
if err == nil && imageID != localImage.ID() {
logrus.Errorf("the image %s already exists, renaming the old one with ID %s to empty string", dst, localImage.ID())
}

pullInfo, err := ir.getPullRefPair(srcRef, dst)
if err != nil {
return nil, err
}
res = append(res, pullInfo)
}
return &pullGoal{
refPairs: res,
pullAllPairs: true,
usedSearchRegistries: false,
searchedRegistries: nil,
}, nil
}

// pullGoalFromImageReference returns a pull goal for a single ImageReference, depending on the used transport.
func (ir *Runtime) pullGoalFromImageReference(ctx context.Context, srcRef types.ImageReference, imgName string, sc *types.SystemContext) (*pullGoal, error) {
span, _ := opentracing.StartSpanFromContext(ctx, "pullGoalFromImageReference")
Expand All @@ -127,52 +173,15 @@ func (ir *Runtime) pullGoalFromImageReference(ctx context.Context, srcRef types.
return nil, err
}
defer tarSource.Close()
manifest, err := tarSource.LoadTarManifest()

items, err := tarSource.LoadTarManifest()
if err != nil {
return nil, errors.Wrapf(err, "error retrieving manifest.json")
}
// 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
reference, err := getImageDigest(ctx, srcRef, sc)
if err != nil {
return nil, err
}
return ir.getSinglePullRefPairGoal(srcRef, reference)
}

if len(manifest[0].RepoTags) == 0 {
// If the input image has no repotags, we need to feed it a dest anyways
digest, err := getImageDigest(ctx, srcRef, sc)
if err != nil {
return nil, err
}
return ir.getSinglePullRefPairGoal(srcRef, digest)
return nil, err
}

// Need to load in all the repo tags from the manifest
res := []pullRefPair{}
for _, dst := range manifest[0].RepoTags {
//check if image exists and gives a warning of untagging
localImage, err := ir.NewFromLocal(dst)
imageID := strings.TrimSuffix(manifest[0].Config, ".json")
if err == nil && imageID != localImage.ID() {
logrus.Errorf("the image %s already exists, renaming the old one with ID %s to empty string", dst, localImage.ID())
}

pullInfo, err := ir.getPullRefPair(srcRef, dst)
if err != nil {
return nil, err
}
res = append(res, pullInfo)
var manifest *tarfile.ManifestItem
if len(items) > 0 {
manifest = &items[0]
}
return &pullGoal{
refPairs: res,
pullAllPairs: true,
usedSearchRegistries: false,
searchedRegistries: nil,
}, nil
return ir.pullGoalFromTarManifest(ctx, manifest, srcRef, sc)

case OCIArchive:
// retrieve the manifest from index.json to access the image name
Expand Down
Loading

0 comments on commit 9efd4e8

Please sign in to comment.