summaryrefslogtreecommitdiff
path: root/pkg/domain/infra/abi/images.go
diff options
context:
space:
mode:
authorValentin Rothberg <rothberg@redhat.com>2020-03-30 12:13:50 +0200
committerValentin Rothberg <rothberg@redhat.com>2020-03-31 13:01:27 +0200
commit3bdad6fa2af41be7e783256f3c8a213dc42ca8f6 (patch)
treeb1d3b9f1b3ee9addd187dc11cfe3585ebd6b02dd /pkg/domain/infra/abi/images.go
parent598bb53d46dfc85b8bcc1e3000736106f80de93e (diff)
downloadpodman-3bdad6fa2af41be7e783256f3c8a213dc42ca8f6.tar.gz
podman-3bdad6fa2af41be7e783256f3c8a213dc42ca8f6.tar.bz2
podman-3bdad6fa2af41be7e783256f3c8a213dc42ca8f6.zip
podmanV2: implement pull
Implement pulling images for the v2 client. What I _really_ don't like is the fact that we are now having a near identical code clone among `pkg/domain/infra/abi` and `pkg/api/handlers/libpod`. Partly because we don't yet have a higher-level pull function and partly because we have redudancy among `pkg/domain` and `pkg/api`. Pull might be a high outlier but I am concerned already by the potential of introducing more redundancy. I'd love to `infra/abi` and `pkg/abi` to really use the same code in the future. Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
Diffstat (limited to 'pkg/domain/infra/abi/images.go')
-rw-r--r--pkg/domain/infra/abi/images.go100
1 files changed, 100 insertions, 0 deletions
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 44420c1e1..ef2879246 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -5,11 +5,22 @@ package abi
import (
"context"
"fmt"
+ "io"
+ "os"
+ "strings"
+ "github.com/containers/image/v5/docker"
+ dockerarchive "github.com/containers/image/v5/docker/archive"
+ "github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/transports/alltransports"
+ "github.com/containers/image/v5/types"
+ "github.com/containers/libpod/libpod/image"
libpodImage "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/util"
"github.com/containers/storage"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
func (ir *ImageEngine) Exists(_ context.Context, nameOrId string) (*entities.BoolReport, error) {
@@ -134,6 +145,95 @@ func ToDomainHistoryLayer(layer *libpodImage.History) entities.ImageHistoryLayer
return l
}
+func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, options entities.ImagePullOptions) (*entities.ImagePullReport, error) {
+ var writer io.Writer
+ if !options.Quiet {
+ writer = os.Stderr
+ }
+
+ dockerPrefix := fmt.Sprintf("%s://", docker.Transport.Name())
+ imageRef, err := alltransports.ParseImageName(rawImage)
+ if err != nil {
+ imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s%s", dockerPrefix, rawImage))
+ if err != nil {
+ return nil, errors.Errorf("invalid image reference %q", rawImage)
+ }
+ }
+
+ // Special-case for docker-archive which allows multiple tags.
+ if imageRef.Transport().Name() == dockerarchive.Transport.Name() {
+ newImage, err := ir.Libpod.ImageRuntime().LoadFromArchiveReference(ctx, imageRef, options.SignaturePolicy, writer)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error pulling image %q", rawImage)
+ }
+ return &entities.ImagePullReport{Images: []string{newImage[0].ID()}}, nil
+ }
+
+ var registryCreds *types.DockerAuthConfig
+ if options.Credentials != "" {
+ creds, err := util.ParseRegistryCreds(options.Credentials)
+ if err != nil {
+ return nil, err
+ }
+ registryCreds = creds
+ }
+ dockerRegistryOptions := image.DockerRegistryOptions{
+ DockerRegistryCreds: registryCreds,
+ DockerCertPath: options.CertDir,
+ OSChoice: options.OverrideOS,
+ ArchitectureChoice: options.OverrideArch,
+ DockerInsecureSkipTLSVerify: options.TLSVerify,
+ }
+
+ if !options.AllTags {
+ newImage, err := ir.Libpod.ImageRuntime().New(ctx, rawImage, options.SignaturePolicy, options.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error pulling image %q", rawImage)
+ }
+ return &entities.ImagePullReport{Images: []string{newImage.ID()}}, nil
+ }
+
+ // --all-tags requires the docker transport
+ if imageRef.Transport().Name() != docker.Transport.Name() {
+ return nil, errors.New("--all-tags requires docker transport")
+ }
+
+ // Trim the docker-transport prefix.
+ rawImage = strings.TrimPrefix(rawImage, docker.Transport.Name())
+
+ // all-tags doesn't work with a tagged reference, so let's check early
+ namedRef, err := reference.Parse(rawImage)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error parsing %q", rawImage)
+ }
+ if _, isTagged := namedRef.(reference.Tagged); isTagged {
+ return nil, errors.New("--all-tags requires a reference without a tag")
+
+ }
+
+ systemContext := image.GetSystemContext("", options.Authfile, false)
+ tags, err := docker.GetRepositoryTags(ctx, systemContext, imageRef)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error getting repository tags")
+ }
+
+ var foundIDs []string
+ for _, tag := range tags {
+ name := rawImage + ":" + tag
+ newImage, err := ir.Libpod.ImageRuntime().New(ctx, name, options.SignaturePolicy, options.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways)
+ if err != nil {
+ logrus.Errorf("error pulling image %q", name)
+ continue
+ }
+ foundIDs = append(foundIDs, newImage.ID())
+ }
+
+ if len(tags) != len(foundIDs) {
+ return nil, errors.Errorf("error pulling image %q", rawImage)
+ }
+ return &entities.ImagePullReport{Images: foundIDs}, nil
+}
+
// func (r *imageRuntime) Delete(ctx context.Context, nameOrId string, opts entities.ImageDeleteOptions) (*entities.ImageDeleteReport, error) {
// image, err := r.libpod.ImageEngine().NewFromLocal(nameOrId)
// if err != nil {