util/multiprovider: Implement Info

Require base provides to implement both content.InfoReaderProvider.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This commit is contained in:
Paweł Gronowski
2024-02-14 13:06:43 +01:00
parent 6b6664a093
commit 55afcdbc0d
5 changed files with 54 additions and 10 deletions

17
cache/remote.go vendored
View File

@@ -18,6 +18,7 @@ import (
"github.com/moby/buildkit/util/leaseutil"
"github.com/moby/buildkit/util/progress/logs"
"github.com/moby/buildkit/util/pull/pullprogress"
digest "github.com/opencontainers/go-digest"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
@@ -85,7 +86,7 @@ func (sr *immutableRef) GetRemotes(ctx context.Context, createIfNeeded bool, ref
return res, nil
}
func appendRemote(parents []*solver.Remote, desc ocispecs.Descriptor, p content.Provider) (res []*solver.Remote) {
func appendRemote(parents []*solver.Remote, desc ocispecs.Descriptor, p content.InfoReaderProvider) (res []*solver.Remote) {
for _, pRemote := range parents {
provider := contentutil.NewMultiProvider(pRemote.Provider)
provider.Add(desc.Digest, p)
@@ -276,6 +277,10 @@ func (mp *lazyMultiProvider) ReaderAt(ctx context.Context, desc ocispecs.Descrip
return mp.mprovider.ReaderAt(ctx, desc)
}
func (mp *lazyMultiProvider) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) {
return mp.mprovider.Info(ctx, dgst)
}
func (mp *lazyMultiProvider) Unlazy(ctx context.Context) error {
eg, egctx := errgroup.WithContext(ctx)
for _, p := range mp.plist {
@@ -304,6 +309,16 @@ func (p lazyRefProvider) ReaderAt(ctx context.Context, desc ocispecs.Descriptor)
return p.ref.cm.ContentStore.ReaderAt(ctx, desc)
}
func (p lazyRefProvider) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) {
if dgst != p.desc.Digest {
return content.Info{}, errdefs.ErrNotFound
}
if err := p.Unlazy(ctx); err != nil {
return content.Info{}, errdefs.ErrNotFound
}
return p.ref.cm.ContentStore.Info(ctx, dgst)
}
func (p lazyRefProvider) Unlazy(ctx context.Context) error {
_, err := p.ref.cm.unlazyG.Do(ctx, string(p.desc.Digest), func(ctx context.Context) (_ struct{}, rerr error) {
if isLazy, err := p.ref.isLazy(ctx); err != nil {

View File

@@ -10,6 +10,7 @@ import (
"github.com/moby/buildkit/solver"
digest "github.com/opencontainers/go-digest"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
func NewCacheChains() *CacheChains {
@@ -120,6 +121,20 @@ type DescriptorProviderPair struct {
Provider content.Provider
}
func (p DescriptorProviderPair) ReaderAt(ctx context.Context, desc ocispecs.Descriptor) (content.ReaderAt, error) {
return p.Provider.ReaderAt(ctx, desc)
}
func (p DescriptorProviderPair) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) {
if dgst != p.Descriptor.Digest {
return content.Info{}, errors.Errorf("content not found %s", dgst)
}
return content.Info{
Digest: p.Descriptor.Digest,
Size: p.Descriptor.Size,
}, nil
}
// item is an implementation of a record in the cache chain. After validation,
// normalization and marshalling into the cache config, the item results form
// into the "layers", while the digests and the links form into the "records".

View File

@@ -82,7 +82,7 @@ func parseRecord(cc CacheConfig, idx int, provider DescriptorProvider, t solver.
}
remote.Descriptors = append(remote.Descriptors, descPair.Descriptor)
mp.Add(descPair.Descriptor.Digest, descPair.Provider)
mp.Add(descPair.Descriptor.Digest, descPair)
}
if remote != nil {
remote.Provider = mp
@@ -123,12 +123,12 @@ func getRemoteChain(layers []CacheLayer, idx int, provider DescriptorProvider, v
}
r.Descriptors = append(r.Descriptors, descPair.Descriptor)
mp := contentutil.NewMultiProvider(r.Provider)
mp.Add(descPair.Descriptor.Digest, descPair.Provider)
mp.Add(descPair.Descriptor.Digest, descPair)
r.Provider = mp
return r, nil
}
return &solver.Remote{
Descriptors: []ocispecs.Descriptor{descPair.Descriptor},
Provider: descPair.Provider,
Provider: descPair,
}, nil
}

View File

@@ -142,7 +142,7 @@ type CacheExporterRecord interface {
// TODO: add closer to keep referenced data from getting deleted
type Remote struct {
Descriptors []ocispecs.Descriptor
Provider content.Provider
Provider content.InfoReaderProvider
}
// CacheLink is a link between two cache records

View File

@@ -13,18 +13,18 @@ import (
)
// NewMultiProvider creates a new mutable provider with a base provider
func NewMultiProvider(base content.Provider) *MultiProvider {
func NewMultiProvider(base content.InfoReaderProvider) *MultiProvider {
return &MultiProvider{
base: base,
sub: map[digest.Digest]content.Provider{},
sub: map[digest.Digest]content.InfoReaderProvider{},
}
}
// MultiProvider is a provider backed by a mutable map of providers
type MultiProvider struct {
mu sync.RWMutex
base content.Provider
sub map[digest.Digest]content.Provider
base content.InfoReaderProvider
sub map[digest.Digest]content.InfoReaderProvider
}
func (mp *MultiProvider) SnapshotLabels(descs []ocispecs.Descriptor, index int) map[string]string {
@@ -85,8 +85,22 @@ func (mp *MultiProvider) ReaderAt(ctx context.Context, desc ocispecs.Descriptor)
return mp.base.ReaderAt(ctx, desc)
}
// Info returns a content.Info
func (mp *MultiProvider) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) {
mp.mu.RLock()
if p, ok := mp.sub[dgst]; ok {
mp.mu.RUnlock()
return p.Info(ctx, dgst)
}
mp.mu.RUnlock()
if mp.base == nil {
return content.Info{}, errors.Wrapf(errdefs.ErrNotFound, "content %v", dgst)
}
return mp.base.Info(ctx, dgst)
}
// Add adds a new child provider for a specific digest
func (mp *MultiProvider) Add(dgst digest.Digest, p content.Provider) {
func (mp *MultiProvider) Add(dgst digest.Digest, p content.InfoReaderProvider) {
mp.mu.Lock()
defer mp.mu.Unlock()
mp.sub[dgst] = p