Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
| ... | ... |
@@ -53,6 +53,7 @@ type SourceOpt struct {
|
| 53 | 53 |
MetadataStore metadata.V2MetadataService |
| 54 | 54 |
ImageStore image.Store |
| 55 | 55 |
ResolverOpt resolver.ResolveOptionsFunc |
| 56 |
+ LayerStore layer.Store |
|
| 56 | 57 |
} |
| 57 | 58 |
|
| 58 | 59 |
type imageSource struct {
|
| ... | ... |
@@ -360,6 +361,23 @@ func (p *puller) CacheKey(ctx context.Context, index int) (string, bool, error) |
| 360 | 360 |
return k, true, nil |
| 361 | 361 |
} |
| 362 | 362 |
|
| 363 |
+func (p *puller) getRef(ctx context.Context, diffIDs []layer.DiffID, opts ...cache.RefOption) (cache.ImmutableRef, error) {
|
|
| 364 |
+ var parent cache.ImmutableRef |
|
| 365 |
+ if len(diffIDs) > 1 {
|
|
| 366 |
+ var err error |
|
| 367 |
+ parent, err = p.getRef(ctx, diffIDs[:len(diffIDs)-1], opts...) |
|
| 368 |
+ if err != nil {
|
|
| 369 |
+ return nil, err |
|
| 370 |
+ } |
|
| 371 |
+ defer parent.Release(context.TODO()) |
|
| 372 |
+ } |
|
| 373 |
+ return p.is.CacheAccessor.GetByBlob(ctx, ocispec.Descriptor{
|
|
| 374 |
+ Annotations: map[string]string{
|
|
| 375 |
+ "containerd.io/uncompressed": diffIDs[len(diffIDs)-1].String(), |
|
| 376 |
+ }, |
|
| 377 |
+ }, parent, opts...) |
|
| 378 |
+} |
|
| 379 |
+ |
|
| 363 | 380 |
func (p *puller) Snapshot(ctx context.Context) (cache.ImmutableRef, error) {
|
| 364 | 381 |
p.resolveLocal() |
| 365 | 382 |
if err := p.resolve(ctx); err != nil {
|
| ... | ... |
@@ -372,11 +390,15 @@ func (p *puller) Snapshot(ctx context.Context) (cache.ImmutableRef, error) {
|
| 372 | 372 |
if len(img.RootFS.DiffIDs) == 0 {
|
| 373 | 373 |
return nil, nil |
| 374 | 374 |
} |
| 375 |
- ref, err := p.is.CacheAccessor.GetFromSnapshotter(ctx, string(img.RootFS.ChainID()), cache.WithDescription(fmt.Sprintf("from local %s", p.ref)))
|
|
| 376 |
- if err != nil {
|
|
| 377 |
- return nil, err |
|
| 375 |
+ l, err := p.is.LayerStore.Get(img.RootFS.ChainID()) |
|
| 376 |
+ if err == nil {
|
|
| 377 |
+ layer.ReleaseAndLog(p.is.LayerStore, l) |
|
| 378 |
+ ref, err := p.getRef(ctx, img.RootFS.DiffIDs, cache.WithDescription(fmt.Sprintf("from local %s", p.ref)))
|
|
| 379 |
+ if err != nil {
|
|
| 380 |
+ return nil, err |
|
| 381 |
+ } |
|
| 382 |
+ return ref, nil |
|
| 378 | 383 |
} |
| 379 |
- return ref, nil |
|
| 380 | 384 |
} |
| 381 | 385 |
} |
| 382 | 386 |
|
| ... | ... |
@@ -550,7 +572,7 @@ func (p *puller) Snapshot(ctx context.Context) (cache.ImmutableRef, error) {
|
| 550 | 550 |
return nil, err |
| 551 | 551 |
} |
| 552 | 552 |
|
| 553 |
- ref, err := p.is.CacheAccessor.GetFromSnapshotter(ctx, string(rootFS.ChainID()), cache.WithDescription(fmt.Sprintf("pulled from %s", p.ref)))
|
|
| 553 |
+ ref, err := p.getRef(ctx, rootFS.DiffIDs, cache.WithDescription(fmt.Sprintf("pulled from %s", p.ref)))
|
|
| 554 | 554 |
release() |
| 555 | 555 |
if err != nil {
|
| 556 | 556 |
return nil, err |
| ... | ... |
@@ -51,10 +51,8 @@ type snapshotter struct {
|
| 51 | 51 |
reg graphIDRegistrar |
| 52 | 52 |
} |
| 53 | 53 |
|
| 54 |
-var _ snapshot.SnapshotterBase = &snapshotter{}
|
|
| 55 |
- |
|
| 56 | 54 |
// NewSnapshotter creates a new snapshotter |
| 57 |
-func NewSnapshotter(opt Opt) (snapshot.SnapshotterBase, error) {
|
|
| 55 |
+func NewSnapshotter(opt Opt) (snapshot.Snapshotter, error) {
|
|
| 58 | 56 |
dbPath := filepath.Join(opt.Root, "snapshots.db") |
| 59 | 57 |
db, err := bolt.Open(dbPath, 0600, nil) |
| 60 | 58 |
if err != nil {
|
| ... | ... |
@@ -87,11 +85,11 @@ func (s *snapshotter) Prepare(ctx context.Context, key, parent string, opts ...s |
| 87 | 87 |
origParent := parent |
| 88 | 88 |
if parent != "" {
|
| 89 | 89 |
if l, err := s.getLayer(parent, false); err != nil {
|
| 90 |
- return err |
|
| 90 |
+ return errors.Wrapf(err, "failed to get parent layer %s", parent) |
|
| 91 | 91 |
} else if l != nil {
|
| 92 | 92 |
parent, err = getGraphID(l) |
| 93 | 93 |
if err != nil {
|
| 94 |
- return err |
|
| 94 |
+ return errors.Wrapf(err, "failed to get parent graphid %s", l.ChainID()) |
|
| 95 | 95 |
} |
| 96 | 96 |
} else {
|
| 97 | 97 |
parent, _ = s.getGraphDriverID(parent) |
| ... | ... |
@@ -146,7 +144,7 @@ func (s *snapshotter) getLayer(key string, withCommitted bool) (layer.Layer, err |
| 146 | 146 |
return nil |
| 147 | 147 |
}); err != nil {
|
| 148 | 148 |
s.mu.Unlock() |
| 149 |
- return nil, err |
|
| 149 |
+ return nil, errors.WithStack(err) |
|
| 150 | 150 |
} |
| 151 | 151 |
if id == "" {
|
| 152 | 152 |
s.mu.Unlock() |
| ... | ... |
@@ -157,12 +155,12 @@ func (s *snapshotter) getLayer(key string, withCommitted bool) (layer.Layer, err |
| 157 | 157 |
l, err = s.opt.LayerStore.Get(id) |
| 158 | 158 |
if err != nil {
|
| 159 | 159 |
s.mu.Unlock() |
| 160 |
- return nil, err |
|
| 160 |
+ return nil, errors.WithStack(err) |
|
| 161 | 161 |
} |
| 162 | 162 |
s.refs[key] = l |
| 163 | 163 |
if err := s.db.Update(func(tx *bolt.Tx) error {
|
| 164 | 164 |
_, err := tx.CreateBucketIfNotExists([]byte(key)) |
| 165 |
- return err |
|
| 165 |
+ return errors.WithStack(err) |
|
| 166 | 166 |
}); err != nil {
|
| 167 | 167 |
s.mu.Unlock() |
| 168 | 168 |
return nil, err |
| ... | ... |
@@ -10,7 +10,6 @@ import ( |
| 10 | 10 |
"sync" |
| 11 | 11 |
"time" |
| 12 | 12 |
|
| 13 |
- "github.com/containerd/containerd/content" |
|
| 14 | 13 |
"github.com/containerd/containerd/platforms" |
| 15 | 14 |
"github.com/docker/docker/api/types" |
| 16 | 15 |
"github.com/docker/docker/api/types/backend" |
| ... | ... |
@@ -468,14 +467,6 @@ func (sp *pruneProxy) SendMsg(m interface{}) error {
|
| 468 | 468 |
return nil |
| 469 | 469 |
} |
| 470 | 470 |
|
| 471 |
-type contentStoreNoLabels struct {
|
|
| 472 |
- content.Store |
|
| 473 |
-} |
|
| 474 |
- |
|
| 475 |
-func (c *contentStoreNoLabels) Update(ctx context.Context, info content.Info, fieldpaths ...string) (content.Info, error) {
|
|
| 476 |
- return content.Info{}, nil
|
|
| 477 |
-} |
|
| 478 |
- |
|
| 479 | 471 |
type wrapRC struct {
|
| 480 | 472 |
io.ReadCloser |
| 481 | 473 |
once sync.Once |
| ... | ... |
@@ -6,7 +6,9 @@ import ( |
| 6 | 6 |
"path/filepath" |
| 7 | 7 |
|
| 8 | 8 |
"github.com/containerd/containerd/content/local" |
| 9 |
+ ctdmetadata "github.com/containerd/containerd/metadata" |
|
| 9 | 10 |
"github.com/containerd/containerd/platforms" |
| 11 |
+ "github.com/containerd/containerd/snapshots" |
|
| 10 | 12 |
"github.com/docker/docker/api/types" |
| 11 | 13 |
"github.com/docker/docker/api/types/filters" |
| 12 | 14 |
"github.com/docker/docker/builder/builder-next/adapters/containerimage" |
| ... | ... |
@@ -29,13 +31,15 @@ import ( |
| 29 | 29 |
dockerfile "github.com/moby/buildkit/frontend/dockerfile/builder" |
| 30 | 30 |
"github.com/moby/buildkit/frontend/gateway" |
| 31 | 31 |
"github.com/moby/buildkit/frontend/gateway/forwarder" |
| 32 |
- "github.com/moby/buildkit/snapshot/blobmapping" |
|
| 32 |
+ containerdsnapshot "github.com/moby/buildkit/snapshot/containerd" |
|
| 33 | 33 |
"github.com/moby/buildkit/solver/bboltcachestorage" |
| 34 | 34 |
"github.com/moby/buildkit/util/binfmt_misc" |
| 35 | 35 |
"github.com/moby/buildkit/util/entitlements" |
| 36 |
+ "github.com/moby/buildkit/util/leaseutil" |
|
| 36 | 37 |
"github.com/moby/buildkit/worker" |
| 37 | 38 |
specs "github.com/opencontainers/image-spec/specs-go/v1" |
| 38 | 39 |
"github.com/pkg/errors" |
| 40 |
+ bolt "go.etcd.io/bbolt" |
|
| 39 | 41 |
) |
| 40 | 42 |
|
| 41 | 43 |
func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
|
| ... | ... |
@@ -55,7 +59,7 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
|
| 55 | 55 |
return nil, errors.Errorf("could not access graphdriver")
|
| 56 | 56 |
} |
| 57 | 57 |
|
| 58 |
- sbase, err := snapshot.NewSnapshotter(snapshot.Opt{
|
|
| 58 |
+ snapshotter, err := snapshot.NewSnapshotter(snapshot.Opt{
|
|
| 59 | 59 |
GraphDriver: driver, |
| 60 | 60 |
LayerStore: dist.LayerStore, |
| 61 | 61 |
Root: root, |
| ... | ... |
@@ -69,20 +73,22 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
|
| 69 | 69 |
if err != nil {
|
| 70 | 70 |
return nil, err |
| 71 | 71 |
} |
| 72 |
- store = &contentStoreNoLabels{store}
|
|
| 72 |
+ |
|
| 73 |
+ db, err := bolt.Open(filepath.Join(root, "containerdmeta.db"), 0644, nil) |
|
| 74 |
+ if err != nil {
|
|
| 75 |
+ return nil, errors.WithStack(err) |
|
| 76 |
+ } |
|
| 77 |
+ |
|
| 78 |
+ mdb := ctdmetadata.NewDB(db, store, map[string]snapshots.Snapshotter{})
|
|
| 79 |
+ |
|
| 80 |
+ store = containerdsnapshot.NewContentStore(mdb.ContentStore(), "buildkit") |
|
| 73 | 81 |
|
| 74 | 82 |
md, err := metadata.NewStore(filepath.Join(root, "metadata.db")) |
| 75 | 83 |
if err != nil {
|
| 76 | 84 |
return nil, err |
| 77 | 85 |
} |
| 78 | 86 |
|
| 79 |
- snapshotter := blobmapping.NewSnapshotter(blobmapping.Opt{
|
|
| 80 |
- Content: store, |
|
| 81 |
- Snapshotter: sbase, |
|
| 82 |
- MetadataStore: md, |
|
| 83 |
- }) |
|
| 84 |
- |
|
| 85 |
- layerGetter, ok := sbase.(imagerefchecker.LayerGetter) |
|
| 87 |
+ layerGetter, ok := snapshotter.(imagerefchecker.LayerGetter) |
|
| 86 | 88 |
if !ok {
|
| 87 | 89 |
return nil, errors.Errorf("snapshotter does not implement layergetter")
|
| 88 | 90 |
} |
| ... | ... |
@@ -96,6 +102,8 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
|
| 96 | 96 |
Snapshotter: snapshotter, |
| 97 | 97 |
MetadataStore: md, |
| 98 | 98 |
PruneRefChecker: refChecker, |
| 99 |
+ LeaseManager: leaseutil.WithNamespace(ctdmetadata.NewLeaseManager(mdb), "buildkit"), |
|
| 100 |
+ ContentStore: store, |
|
| 99 | 101 |
}) |
| 100 | 102 |
if err != nil {
|
| 101 | 103 |
return nil, err |
| ... | ... |
@@ -109,6 +117,7 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
|
| 109 | 109 |
ImageStore: dist.ImageStore, |
| 110 | 110 |
ReferenceStore: dist.ReferenceStore, |
| 111 | 111 |
ResolverOpt: opt.ResolverOpt, |
| 112 |
+ LayerStore: dist.LayerStore, |
|
| 112 | 113 |
}) |
| 113 | 114 |
if err != nil {
|
| 114 | 115 |
return nil, err |
| ... | ... |
@@ -121,7 +130,7 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
|
| 121 | 121 |
return nil, err |
| 122 | 122 |
} |
| 123 | 123 |
|
| 124 |
- differ, ok := sbase.(containerimageexp.Differ) |
|
| 124 |
+ differ, ok := snapshotter.(containerimageexp.Differ) |
|
| 125 | 125 |
if !ok {
|
| 126 | 126 |
return nil, errors.Errorf("snapshotter doesn't support differ")
|
| 127 | 127 |
} |
| ... | ... |
@@ -145,7 +154,7 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
|
| 145 | 145 |
return nil, errors.Wrap(err, "could not get builder GC policy") |
| 146 | 146 |
} |
| 147 | 147 |
|
| 148 |
- layers, ok := sbase.(mobyworker.LayerAccess) |
|
| 148 |
+ layers, ok := snapshotter.(mobyworker.LayerAccess) |
|
| 149 | 149 |
if !ok {
|
| 150 | 150 |
return nil, errors.Errorf("snapshotter doesn't support differ")
|
| 151 | 151 |
} |
| ... | ... |
@@ -6,6 +6,7 @@ import ( |
| 6 | 6 |
"github.com/docker/docker/image" |
| 7 | 7 |
"github.com/docker/docker/layer" |
| 8 | 8 |
"github.com/moby/buildkit/cache" |
| 9 |
+ digest "github.com/opencontainers/go-digest" |
|
| 9 | 10 |
) |
| 10 | 11 |
|
| 11 | 12 |
// LayerGetter abstracts away the snapshotter |
| ... | ... |
@@ -57,7 +58,8 @@ type checker struct {
|
| 57 | 57 |
cache map[string]bool |
| 58 | 58 |
} |
| 59 | 59 |
|
| 60 |
-func (c *checker) Exists(key string) bool {
|
|
| 60 |
+func (c *checker) Exists(key string, chain []digest.Digest) bool {
|
|
| 61 |
+ // TODO: neeeds update |
|
| 61 | 62 |
if c.opt.ImageStore == nil {
|
| 62 | 63 |
return false |
| 63 | 64 |
} |
| ... | ... |
@@ -305,6 +305,23 @@ func (w *Worker) PruneCacheMounts(ctx context.Context, ids []string) error {
|
| 305 | 305 |
return nil |
| 306 | 306 |
} |
| 307 | 307 |
|
| 308 |
+func (w *Worker) getRef(ctx context.Context, diffIDs []layer.DiffID, opts ...cache.RefOption) (cache.ImmutableRef, error) {
|
|
| 309 |
+ var parent cache.ImmutableRef |
|
| 310 |
+ if len(diffIDs) > 1 {
|
|
| 311 |
+ var err error |
|
| 312 |
+ parent, err = w.getRef(ctx, diffIDs[:len(diffIDs)-1], opts...) |
|
| 313 |
+ if err != nil {
|
|
| 314 |
+ return nil, err |
|
| 315 |
+ } |
|
| 316 |
+ defer parent.Release(context.TODO()) |
|
| 317 |
+ } |
|
| 318 |
+ return w.CacheManager.GetByBlob(context.TODO(), ocispec.Descriptor{
|
|
| 319 |
+ Annotations: map[string]string{
|
|
| 320 |
+ "containerd.io/uncompressed": diffIDs[len(diffIDs)-1].String(), |
|
| 321 |
+ }, |
|
| 322 |
+ }, parent, opts...) |
|
| 323 |
+} |
|
| 324 |
+ |
|
| 308 | 325 |
// FromRemote converts a remote snapshot reference to a local one |
| 309 | 326 |
func (w *Worker) FromRemote(ctx context.Context, remote *solver.Remote) (cache.ImmutableRef, error) {
|
| 310 | 327 |
rootfs, err := getLayers(ctx, remote.Descriptors) |
| ... | ... |
@@ -353,7 +370,7 @@ func (w *Worker) FromRemote(ctx context.Context, remote *solver.Remote) (cache.I |
| 353 | 353 |
if v, ok := remote.Descriptors[i].Annotations["buildkit/description"]; ok {
|
| 354 | 354 |
descr = v |
| 355 | 355 |
} |
| 356 |
- ref, err := w.CacheManager.GetFromSnapshotter(ctx, string(layer.CreateChainID(rootFS.DiffIDs[:i+1])), cache.WithDescription(descr), cache.WithCreationTime(tm)) |
|
| 356 |
+ ref, err := w.getRef(ctx, rootFS.DiffIDs[:i+1], cache.WithDescription(descr), cache.WithCreationTime(tm)) |
|
| 357 | 357 |
if err != nil {
|
| 358 | 358 |
return nil, err |
| 359 | 359 |
} |