1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

builder-next: Refactor using buildkit's resolver pool

Signed-off-by: Tibor Vass <tibor@docker.com>
This commit is contained in:
Tibor Vass 2020-11-13 02:23:01 +00:00
parent de56a90929
commit 3756668adb

View file

@ -9,7 +9,6 @@ import (
"path" "path"
"runtime" "runtime"
"sync" "sync"
"sync/atomic"
"time" "time"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
@ -36,7 +35,7 @@ import (
"github.com/moby/buildkit/util/flightcontrol" "github.com/moby/buildkit/util/flightcontrol"
"github.com/moby/buildkit/util/imageutil" "github.com/moby/buildkit/util/imageutil"
"github.com/moby/buildkit/util/progress" "github.com/moby/buildkit/util/progress"
_ "github.com/moby/buildkit/util/resolver" "github.com/moby/buildkit/util/resolver"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/identity" "github.com/opencontainers/image-spec/identity"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@ -61,17 +60,11 @@ type SourceOpt struct {
type Source struct { type Source struct {
SourceOpt SourceOpt
g flightcontrol.Group g flightcontrol.Group
resolverCache *resolverCache
} }
// NewSource creates a new image source // NewSource creates a new image source
func NewSource(opt SourceOpt) (*Source, error) { func NewSource(opt SourceOpt) (*Source, error) {
is := &Source{ return &Source{SourceOpt: opt}, nil
SourceOpt: opt,
resolverCache: nil, //newResolverCache(),
}
return is, nil
} }
// ID returns image scheme identifier // ID returns image scheme identifier
@ -79,17 +72,6 @@ func (is *Source) ID() string {
return source.DockerImageScheme return source.DockerImageScheme
} }
func (is *Source) getResolver(hosts docker.RegistryHosts, ref string, sm *session.Manager, g session.Group) remotes.Resolver {
if res := is.resolverCache.Get(ref, g); res != nil {
return res
}
//auth := resolver.NewSessionAuthenticator(sm, g)
//r := resolver.New(hosts, auth)
//r = is.resolverCache.Add(ref, auth, r, g)
//return r
return nil
}
func (is *Source) resolveLocal(refStr string) (*image.Image, error) { func (is *Source) resolveLocal(refStr string) (*image.Image, error) {
ref, err := distreference.ParseNormalizedNamed(refStr) ref, err := distreference.ParseNormalizedNamed(refStr)
if err != nil { if err != nil {
@ -112,7 +94,8 @@ func (is *Source) resolveRemote(ctx context.Context, ref string, platform *ocisp
dt []byte dt []byte
} }
res, err := is.g.Do(ctx, ref, func(ctx context.Context) (interface{}, error) { res, err := is.g.Do(ctx, ref, func(ctx context.Context) (interface{}, error) {
dgst, dt, err := imageutil.Config(ctx, ref, is.getResolver(is.RegistryHosts, ref, sm, g), is.ContentStore, nil, platform) res := resolver.DefaultPool.GetResolver(is.RegistryHosts, ref, "pull", sm, g)
dgst, dt, err := imageutil.Config(ctx, ref, res, is.ContentStore, nil, platform)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -199,20 +182,13 @@ type puller struct {
desc ocispec.Descriptor desc ocispec.Descriptor
ref string ref string
resolveErr error resolveErr error
resolverInstance remotes.Resolver
resolverOnce sync.Once
config []byte config []byte
platform ocispec.Platform platform ocispec.Platform
sm *session.Manager sm *session.Manager
} }
func (p *puller) resolver(g session.Group) remotes.Resolver { func (p *puller) resolver(g session.Group) remotes.Resolver {
p.resolverOnce.Do(func() { return resolver.DefaultPool.GetResolver(p.is.RegistryHosts, p.src.Reference.String(), "pull", p.sm, g)
if p.resolverInstance == nil {
p.resolverInstance = p.is.getResolver(p.is.RegistryHosts, p.src.Reference.String(), p.sm, g)
}
})
return p.resolverInstance
} }
func (p *puller) mainManifestKey(dgst digest.Digest, platform ocispec.Platform) (digest.Digest, error) { func (p *puller) mainManifestKey(dgst digest.Digest, platform ocispec.Platform) (digest.Digest, error) {
@ -428,10 +404,6 @@ func (p *puller) Snapshot(ctx context.Context, g session.Group) (cache.Immutable
} }
platform := platforms.Only(p.platform) platform := platforms.Only(p.platform)
// workaround for GCR bug that requires a request to manifest endpoint for authentication to work.
// if current resolver has not used manifests do a dummy request.
// in most cases resolver should be cached and extra request is not needed.
ensureManifestRequested(ctx, p.resolver(g), p.ref)
var ( var (
schema1Converter *schema1.Converter schema1Converter *schema1.Converter
@ -847,95 +819,6 @@ func resolveModeToString(rm source.ResolveMode) string {
return "" return ""
} }
type resolverCache struct {
mu sync.Mutex
m map[string]cachedResolver
}
type cachedResolver struct {
counter int64 // needs to be 64bit aligned for 32bit systems
timeout time.Time
remotes.Resolver
auth *struct{}
}
func (cr *cachedResolver) Resolve(ctx context.Context, ref string) (name string, desc ocispec.Descriptor, err error) {
atomic.AddInt64(&cr.counter, 1)
return cr.Resolver.Resolve(ctx, ref)
}
func (r *resolverCache) Add(ref string, auth *struct{}, resolver remotes.Resolver, g session.Group) *cachedResolver {
r.mu.Lock()
defer r.mu.Unlock()
ref = r.repo(ref)
cr, ok := r.m[ref]
cr.timeout = time.Now().Add(time.Minute)
if ok {
return &cr
}
cr.Resolver = resolver
cr.auth = auth
r.m[ref] = cr
return &cr
}
func (r *resolverCache) repo(refStr string) string {
ref, err := distreference.ParseNormalizedNamed(refStr)
if err != nil {
return refStr
}
return ref.Name()
}
func (r *resolverCache) Get(ref string, g session.Group) *cachedResolver {
r.mu.Lock()
defer r.mu.Unlock()
ref = r.repo(ref)
cr, ok := r.m[ref]
if ok {
return &cr
}
return nil
}
func (r *resolverCache) clean(now time.Time) {
r.mu.Lock()
for k, cr := range r.m {
if now.After(cr.timeout) {
delete(r.m, k)
}
}
r.mu.Unlock()
}
func newResolverCache() *resolverCache {
rc := &resolverCache{
m: map[string]cachedResolver{},
}
t := time.NewTicker(time.Minute)
go func() {
for {
rc.clean(<-t.C)
}
}()
return rc
}
func ensureManifestRequested(ctx context.Context, res remotes.Resolver, ref string) {
cr, ok := res.(*cachedResolver)
if !ok {
return
}
if atomic.LoadInt64(&cr.counter) == 0 {
res.Resolve(ctx, ref)
}
}
func platformMatches(img *image.Image, p *ocispec.Platform) bool { func platformMatches(img *image.Image, p *ocispec.Platform) bool {
if img.Architecture != p.Architecture { if img.Architecture != p.Architecture {
return false return false