|
@@ -2,11 +2,20 @@ package worker
|
|
|
|
|
|
import (
|
|
|
"context"
|
|
|
+ "fmt"
|
|
|
"io"
|
|
|
+ "io/ioutil"
|
|
|
+ "runtime"
|
|
|
"time"
|
|
|
|
|
|
"github.com/containerd/containerd/content"
|
|
|
"github.com/containerd/containerd/rootfs"
|
|
|
+ "github.com/docker/docker/distribution"
|
|
|
+ distmetadata "github.com/docker/docker/distribution/metadata"
|
|
|
+ "github.com/docker/docker/distribution/xfer"
|
|
|
+ "github.com/docker/docker/image"
|
|
|
+ "github.com/docker/docker/layer"
|
|
|
+ pkgprogress "github.com/docker/docker/pkg/progress"
|
|
|
"github.com/moby/buildkit/cache"
|
|
|
"github.com/moby/buildkit/cache/metadata"
|
|
|
"github.com/moby/buildkit/client"
|
|
@@ -22,10 +31,12 @@ import (
|
|
|
"github.com/moby/buildkit/source/git"
|
|
|
"github.com/moby/buildkit/source/http"
|
|
|
"github.com/moby/buildkit/source/local"
|
|
|
+ "github.com/moby/buildkit/util/contentutil"
|
|
|
"github.com/moby/buildkit/util/progress"
|
|
|
digest "github.com/opencontainers/go-digest"
|
|
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
|
"github.com/pkg/errors"
|
|
|
+ netcontext "golang.org/x/net/context"
|
|
|
)
|
|
|
|
|
|
// TODO: this file should be removed. containerd defines ContainerdWorker, oci defines OCIWorker. There is no base worker.
|
|
@@ -33,16 +44,18 @@ import (
|
|
|
// WorkerOpt is specific to a worker.
|
|
|
// See also CommonOpt.
|
|
|
type WorkerOpt struct {
|
|
|
- ID string
|
|
|
- Labels map[string]string
|
|
|
- SessionManager *session.Manager
|
|
|
- MetadataStore *metadata.Store
|
|
|
- Executor executor.Executor
|
|
|
- Snapshotter snapshot.Snapshotter
|
|
|
- ContentStore content.Store
|
|
|
- CacheManager cache.Manager
|
|
|
- ImageSource source.Source
|
|
|
- Exporters map[string]exporter.Exporter
|
|
|
+ ID string
|
|
|
+ Labels map[string]string
|
|
|
+ SessionManager *session.Manager
|
|
|
+ MetadataStore *metadata.Store
|
|
|
+ Executor executor.Executor
|
|
|
+ Snapshotter snapshot.Snapshotter
|
|
|
+ ContentStore content.Store
|
|
|
+ CacheManager cache.Manager
|
|
|
+ ImageSource source.Source
|
|
|
+ Exporters map[string]exporter.Exporter
|
|
|
+ DownloadManager distribution.RootFSDownloadManager
|
|
|
+ V2MetadataService distmetadata.V2MetadataService
|
|
|
// ImageStore images.Store // optional
|
|
|
}
|
|
|
|
|
@@ -198,6 +211,43 @@ func (w *Worker) GetRemote(ctx context.Context, ref cache.ImmutableRef) (*solver
|
|
|
}
|
|
|
|
|
|
func (w *Worker) FromRemote(ctx context.Context, remote *solver.Remote) (cache.ImmutableRef, error) {
|
|
|
+ rootfs, err := getLayers(ctx, remote.Descriptors)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ layers := make([]xfer.DownloadDescriptor, 0, len(rootfs))
|
|
|
+
|
|
|
+ for _, l := range rootfs {
|
|
|
+ // ongoing.add(desc)
|
|
|
+ layers = append(layers, &layerDescriptor{
|
|
|
+ desc: l.Blob,
|
|
|
+ diffID: layer.DiffID(l.Diff.Digest),
|
|
|
+ provider: remote.Provider,
|
|
|
+ w: w,
|
|
|
+ pctx: ctx,
|
|
|
+ // ref: l.Blob.Digest.String(),
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ defer func() {
|
|
|
+ for _, l := range rootfs {
|
|
|
+ w.ContentStore.Delete(context.TODO(), l.Blob.Digest)
|
|
|
+ }
|
|
|
+ }()
|
|
|
+
|
|
|
+ r := image.NewRootFS()
|
|
|
+ rootFS, release, err := w.DownloadManager.Download(ctx, *r, runtime.GOOS, layers, &discardProgress{})
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ defer release()
|
|
|
+
|
|
|
+ ref, err := w.CacheManager.Get(ctx, string(rootFS.ChainID()), cache.WithDescription(fmt.Sprintf("imported %s", remote.Descriptors[len(remote.Descriptors)-1].Digest)))
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
// eg, gctx := errgroup.WithContext(ctx)
|
|
|
// for _, desc := range remote.Descriptors {
|
|
|
// func(desc ocispec.Descriptor) {
|
|
@@ -223,7 +273,8 @@ func (w *Worker) FromRemote(ctx context.Context, remote *solver.Remote) (cache.I
|
|
|
// unpackProgressDone(nil)
|
|
|
//
|
|
|
// return w.CacheManager.Get(ctx, chainID, cache.WithDescription(fmt.Sprintf("imported %s", remote.Descriptors[len(remote.Descriptors)-1].Digest)))
|
|
|
- return nil, errors.Errorf("fromremote not implemented")
|
|
|
+ // return nil, errors.Errorf("fromremote not implemented")
|
|
|
+ return ref, nil
|
|
|
}
|
|
|
|
|
|
// utility function. could be moved to the constructor logic?
|
|
@@ -259,6 +310,58 @@ func (w *Worker) FromRemote(ctx context.Context, remote *solver.Remote) (cache.I
|
|
|
// return string(b), nil
|
|
|
// }
|
|
|
|
|
|
+type discardProgress struct{}
|
|
|
+
|
|
|
+func (_ *discardProgress) WriteProgress(_ pkgprogress.Progress) error {
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// Fetch(ctx context.Context, desc ocispec.Descriptor) (io.ReadCloser, error)
|
|
|
+type layerDescriptor struct {
|
|
|
+ provider content.Provider
|
|
|
+ desc ocispec.Descriptor
|
|
|
+ diffID layer.DiffID
|
|
|
+ // ref ctdreference.Spec
|
|
|
+ w *Worker
|
|
|
+ pctx context.Context
|
|
|
+}
|
|
|
+
|
|
|
+func (ld *layerDescriptor) Key() string {
|
|
|
+ return "v2:" + ld.desc.Digest.String()
|
|
|
+}
|
|
|
+
|
|
|
+func (ld *layerDescriptor) ID() string {
|
|
|
+ return ld.desc.Digest.String()
|
|
|
+}
|
|
|
+
|
|
|
+func (ld *layerDescriptor) DiffID() (layer.DiffID, error) {
|
|
|
+ return ld.diffID, nil
|
|
|
+}
|
|
|
+
|
|
|
+func (ld *layerDescriptor) Download(ctx netcontext.Context, progressOutput pkgprogress.Output) (io.ReadCloser, int64, error) {
|
|
|
+ done := oneOffProgress(ld.pctx, fmt.Sprintf("pulling %s", ld.desc.Digest))
|
|
|
+ if err := contentutil.Copy(ctx, ld.w.ContentStore, ld.provider, ld.desc); err != nil {
|
|
|
+ return nil, 0, done(err)
|
|
|
+ }
|
|
|
+ done(nil)
|
|
|
+
|
|
|
+ ra, err := ld.w.ContentStore.ReaderAt(ctx, ld.desc.Digest)
|
|
|
+ if err != nil {
|
|
|
+ return nil, 0, err
|
|
|
+ }
|
|
|
+
|
|
|
+ return ioutil.NopCloser(content.NewReader(ra)), ld.desc.Size, nil
|
|
|
+}
|
|
|
+
|
|
|
+func (ld *layerDescriptor) Close() {
|
|
|
+ // ld.is.ContentStore.Delete(context.TODO(), ld.desc.Digest)
|
|
|
+}
|
|
|
+
|
|
|
+func (ld *layerDescriptor) Registered(diffID layer.DiffID) {
|
|
|
+ // Cache mapping from this layer's DiffID to the blobsum
|
|
|
+ ld.w.V2MetadataService.Add(diffID, distmetadata.V2Metadata{Digest: ld.desc.Digest})
|
|
|
+}
|
|
|
+
|
|
|
func getLayers(ctx context.Context, descs []ocispec.Descriptor) ([]rootfs.Layer, error) {
|
|
|
layers := make([]rootfs.Layer, len(descs))
|
|
|
for i, desc := range descs {
|