Skip to content

Commit

Permalink
on pull image actually do source and export
Browse files Browse the repository at this point in the history
closes #110

Signed-off-by: Jess Frazelle <[email protected]>
  • Loading branch information
jessfraz committed Jun 5, 2018
1 parent 2e8fcbd commit b38a9eb
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 23 deletions.
80 changes: 57 additions & 23 deletions client/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ package client
import (
"context"
"fmt"
"time"

"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/platforms"
"github.com/docker/distribution/reference"
"github.com/moby/buildkit/cache"
imageexporter "github.com/moby/buildkit/exporter/containerimage"
"github.com/moby/buildkit/source"
"github.com/moby/buildkit/util/pull"
"github.com/moby/buildkit/source/containerimage"
)

// Pull retrieves an image from a remote registry.
Expand All @@ -36,36 +35,71 @@ func (c *Client) Pull(ctx context.Context, image string) (*ListedImage, error) {
return nil, fmt.Errorf("creating worker opt failed: %v", err)
}

puller := &pull.Puller{
cm, err := cache.NewManager(cache.ManagerOpt{
Snapshotter: opt.Snapshotter,
MetadataStore: opt.MetadataStore,
})
if err != nil {
return nil, err
}

// Create the source for the pull.
srcOpt := containerimage.SourceOpt{
SessionManager: opt.SessionManager,
Snapshotter: opt.Snapshotter,
ContentStore: opt.ContentStore,
Applier: opt.Applier,
CacheAccessor: cm,
ImageStore: opt.ImageStore,
}
src, err := containerimage.NewSource(srcOpt)
if err != nil {
return nil, err
}
s, err := src.Resolve(ctx, identifier)
if err != nil {
return nil, err
}
ref, err := s.Snapshot(ctx)
if err != nil {
return nil, err
}

// Create the exporter for the pull.
iw, err := imageexporter.NewImageWriter(imageexporter.WriterOpt{
Snapshotter: opt.Snapshotter,
ContentStore: opt.ContentStore,
Applier: opt.Applier,
Src: identifier.Reference,
Resolver: pull.NewResolver(ctx, opt.SessionManager, opt.ImageStore),
Differ: opt.Differ,
})
if err != nil {
return nil, err
}
expOpt := imageexporter.Opt{
SessionManager: opt.SessionManager,
Images: opt.ImageStore,
ImageWriter: iw,
}
pulled, err := puller.Pull(ctx)
exp, err := imageexporter.New(expOpt)
if err != nil {
return nil, err
}
// Update the target image. Create it if it does not exist.
img := images.Image{
Name: image,
Target: pulled.Descriptor,
CreatedAt: time.Now(),
e, err := exp.Resolve(ctx, map[string]string{"name": image})
if err != nil {
return nil, err
}
if _, err := e.Export(ctx, ref, nil); err != nil {
return nil, err
}
if _, err := opt.ImageStore.Update(ctx, img); err != nil {
if !errdefs.IsNotFound(err) {
return nil, fmt.Errorf("updating image store for %s failed: %v", image, err)
}

// Create it if we didn't find it.
if _, err := opt.ImageStore.Create(ctx, img); err != nil {
return nil, fmt.Errorf("creating image in image store for %s failed: %v", image, err)
}
// Get the image.
img, err := opt.ImageStore.Get(ctx, image)
if err != nil {
return nil, fmt.Errorf("getting image %s from image store failed: %v", image, err)
}
size, err := img.Size(ctx, opt.ContentStore, platforms.Default())
if err != nil {
return nil, fmt.Errorf("calculating size of image %s failed: %v", image, err)
return nil, fmt.Errorf("calculating size of image %s failed: %v", img.Name, err)
}

return &ListedImage{Image: img, ContentSize: size}, nil
}
38 changes: 38 additions & 0 deletions tag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,41 @@ func TestTagImage(t *testing.T) {
t.Fatalf("expected ls output to have tagthing:latest and jess/tagtest:latest but got: %s", out)
}
}

func TestTagImageAndPush(t *testing.T) {
runBuild(t, "tagthingandpush", withDockerfile(`
FROM busybox
RUN echo tagtestandpush
`))

run(t, "tag", "tagthingandpush", "jess/tagtestandpush")

out := run(t, "ls")

if !strings.Contains(out, "tagthingandpush:latest") || !strings.Contains(out, "jess/tagtestandpush:latest") {
t.Fatalf("expected ls output to have tagthingandpush:latest and jess/tagtestandpush:latest but got: %s", out)
}

out, err := doRun([]string{"push", "jess/tagtestandpush"}, nil)
if !strings.Contains(err.Error(), "insufficient_scope: authorization failed") {
t.Fatalf("expected push to fail with 'insufficient_scope: authorization failed' got: %s %v", out, err)
}
}

func TestTagPullAndPush(t *testing.T) {
// Test an official image,
run(t, "pull", "busybox")

run(t, "tag", "busybox", "jess/tagpullandpush")

out := run(t, "ls")

if !strings.Contains(out, "busybox:latest") || !strings.Contains(out, "jess/tagpullandpush:latest") {
t.Fatalf("expected ls output to have busybox:latest and jess/tagpullandpush:latest but got: %s", out)
}

out, err := doRun([]string{"push", "jess/tagpullandpush"}, nil)
if !strings.Contains(err.Error(), "insufficient_scope: authorization failed") {
t.Fatalf("expected push to fail with 'insufficient_scope: authorization failed' got: %s %v", out, err)
}
}

0 comments on commit b38a9eb

Please sign in to comment.