Преглед на файлове

builder-next: fixes for inline cache support

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Tonis Tiigi преди 6 години
родител
ревизия
ddaba80467
променени са 3 файла, в които са добавени 89 реда и са изтрити 7 реда
  1. 11 1
      builder/builder-next/adapters/snapshot/layer.go
  2. 6 1
      builder/builder-next/controller.go
  3. 72 5
      builder/builder-next/worker/worker.go

+ 11 - 1
builder/builder-next/adapters/snapshot/layer.go

@@ -12,12 +12,22 @@ import (
 	"golang.org/x/sync/errgroup"
 )
 
-func (s *snapshotter) EnsureLayer(ctx context.Context, key string) ([]layer.DiffID, error) {
+func (s *snapshotter) GetDiffIDs(ctx context.Context, key string) ([]layer.DiffID, error) {
 	if l, err := s.getLayer(key, true); err != nil {
 		return nil, err
 	} else if l != nil {
 		return getDiffChain(l), nil
 	}
+	return nil, nil
+}
+
+func (s *snapshotter) EnsureLayer(ctx context.Context, key string) ([]layer.DiffID, error) {
+	diffIDs, err := s.GetDiffIDs(ctx, key)
+	if err != nil {
+		return nil, err
+	} else if diffIDs != nil {
+		return diffIDs, nil
+	}
 
 	id, committed := s.getGraphDriverID(key)
 	if !committed {

+ 6 - 1
builder/builder-next/controller.go

@@ -136,6 +136,11 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
 		return nil, errors.Wrap(err, "could not get builder GC policy")
 	}
 
+	layers, ok := sbase.(mobyworker.LayerAccess)
+	if !ok {
+		return nil, errors.Errorf("snapshotter doesn't support differ")
+	}
+
 	wopt := mobyworker.Opt{
 		ID:                "moby",
 		MetadataStore:     md,
@@ -149,6 +154,7 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
 		V2MetadataService: dist.V2MetadataService,
 		Exporter:          exp,
 		Transport:         rt,
+		Layers:            layers,
 	}
 
 	wc := &worker.Controller{}
@@ -174,7 +180,6 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
 		ResolveCacheExporterFuncs: map[string]remotecache.ResolveCacheExporterFunc{
 			"inline": inlineremotecache.ResolveCacheExporterFunc(),
 		},
-		// TODO: set ResolveCacheExporterFunc for exporting cache
 	})
 }
 

+ 72 - 5
builder/builder-next/worker/worker.go

@@ -10,6 +10,7 @@ import (
 	"time"
 
 	"github.com/containerd/containerd/content"
+	"github.com/containerd/containerd/images"
 	"github.com/containerd/containerd/platforms"
 	"github.com/containerd/containerd/rootfs"
 	"github.com/docker/docker/distribution"
@@ -43,6 +44,14 @@ import (
 	"github.com/sirupsen/logrus"
 )
 
+const labelCreatedAt = "buildkit/createdat"
+
+// LayerAccess provides access to a moby layer from a snapshot
+type LayerAccess interface {
+	GetDiffIDs(ctx context.Context, key string) ([]layer.DiffID, error)
+	EnsureLayer(ctx context.Context, key string) ([]layer.DiffID, error)
+}
+
 // Opt defines a structure for creating a worker.
 type Opt struct {
 	ID                string
@@ -58,6 +67,7 @@ type Opt struct {
 	V2MetadataService distmetadata.V2MetadataService
 	Transport         nethttp.RoundTripper
 	Exporter          exporter.Exporter
+	Layers            LayerAccess
 }
 
 // Worker is a local worker instance with dedicated snapshotter, cache, and so on.
@@ -205,7 +215,36 @@ func (w *Worker) Exporter(name string, sm *session.Manager) (exporter.Exporter,
 
 // GetRemote returns a remote snapshot reference for a local one
 func (w *Worker) GetRemote(ctx context.Context, ref cache.ImmutableRef, createIfNeeded bool) (*solver.Remote, error) {
-	return nil, errors.Errorf("getremote not implemented")
+	var diffIDs []layer.DiffID
+	var err error
+	if !createIfNeeded {
+		diffIDs, err = w.Layers.GetDiffIDs(ctx, ref.ID())
+		if err != nil {
+			return nil, err
+		}
+	} else {
+		if err := ref.Finalize(ctx, true); err != nil {
+			return nil, err
+		}
+		diffIDs, err = w.Layers.EnsureLayer(ctx, ref.ID())
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	descriptors := make([]ocispec.Descriptor, len(diffIDs))
+	for i, dgst := range diffIDs {
+		descriptors[i] = ocispec.Descriptor{
+			MediaType: images.MediaTypeDockerSchema2Layer,
+			Digest:    digest.Digest(dgst),
+			Size:      -1,
+		}
+	}
+
+	return &solver.Remote{
+		Descriptors: descriptors,
+		Provider:    &emptyProvider{},
+	}, nil
 }
 
 // FromRemote converts a remote snapshot reference to a local one
@@ -241,11 +280,32 @@ func (w *Worker) FromRemote(ctx context.Context, remote *solver.Remote) (cache.I
 	}
 	defer release()
 
-	ref, err := w.CacheManager.GetFromSnapshotter(ctx, string(rootFS.ChainID()), cache.WithDescription(fmt.Sprintf("imported %s", remote.Descriptors[len(remote.Descriptors)-1].Digest)))
-	if err != nil {
-		return nil, err
+	if len(rootFS.DiffIDs) != len(layers) {
+		return nil, errors.Errorf("invalid layer count mismatch %d vs %d", len(rootFS.DiffIDs), len(layers))
+	}
+
+	for i := range rootFS.DiffIDs {
+		tm := time.Now()
+		if tmstr, ok := remote.Descriptors[i].Annotations[labelCreatedAt]; ok {
+			if err := (&tm).UnmarshalText([]byte(tmstr)); err != nil {
+				return nil, err
+			}
+		}
+		descr := fmt.Sprintf("imported %s", remote.Descriptors[i].Digest)
+		if v, ok := remote.Descriptors[i].Annotations["buildkit/description"]; ok {
+			descr = v
+		}
+		ref, err := w.CacheManager.GetFromSnapshotter(ctx, string(layer.CreateChainID(rootFS.DiffIDs[:i+1])), cache.WithDescription(descr), cache.WithCreationTime(tm))
+		if err != nil {
+			return nil, err
+		}
+		if i == len(remote.Descriptors)-1 {
+			return ref, nil
+		}
+		defer ref.Release(context.TODO())
 	}
-	return ref, nil
+
+	return nil, errors.Errorf("unreachable")
 }
 
 type discardProgress struct{}
@@ -344,3 +404,10 @@ func oneOffProgress(ctx context.Context, id string) func(err error) error {
 type resolveImageConfig interface {
 	ResolveImageConfig(ctx context.Context, ref string, opt gw.ResolveImageConfigOpt, sm *session.Manager) (digest.Digest, []byte, error)
 }
+
+type emptyProvider struct {
+}
+
+func (p *emptyProvider) ReaderAt(ctx context.Context, dec ocispec.Descriptor) (content.ReaderAt, error) {
+	return nil, errors.Errorf("ReaderAt not implemented for empty provider")
+}