mirror of
https://github.com/moby/buildkit.git
synced 2026-08-09 17:18:11 +00:00
86 lines
2.5 KiB
Go
86 lines
2.5 KiB
Go
package source
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/moby/buildkit/cache"
|
|
"github.com/moby/buildkit/session"
|
|
"github.com/moby/buildkit/solver"
|
|
"github.com/moby/buildkit/solver/pb"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// Source implementations provide "root" vertices in the graph that can be
|
|
// constructed from a URI-like string and arbitrary attrs.
|
|
type Source interface {
|
|
// Schemes returns a list of SourceOp identifier schemes that this source
|
|
// should match.
|
|
Schemes() []string
|
|
|
|
// Identifier constructs an Identifier from the given scheme, ref, and attrs,
|
|
// all of which come from a SourceOp.
|
|
Identifier(scheme, ref string, attrs map[string]string, platform *pb.Platform) (Identifier, error)
|
|
|
|
// Resolve constructs an instance of the source from an Identifier.
|
|
Resolve(ctx context.Context, id Identifier, sm *session.Manager, vtx solver.Vertex) (SourceInstance, error)
|
|
}
|
|
|
|
// SourceInstance represents a cacheable vertex created by a Source.
|
|
type SourceInstance interface {
|
|
// CacheKey returns the cache key for the instance.
|
|
CacheKey(ctx context.Context, jobCtx solver.JobContext, index int) (key, pin string, opts solver.CacheOpts, done bool, err error)
|
|
|
|
// Snapshot creates a cache ref for the instance. May return a nil ref if source points to empty content, e.g. image without any layers.
|
|
Snapshot(ctx context.Context, jobCtx solver.JobContext) (cache.ImmutableRef, error)
|
|
}
|
|
|
|
type Manager struct {
|
|
mu sync.Mutex
|
|
schemes map[string]Source
|
|
}
|
|
|
|
func NewManager() (*Manager, error) {
|
|
return &Manager{
|
|
schemes: make(map[string]Source),
|
|
}, nil
|
|
}
|
|
|
|
func (sm *Manager) Register(src Source) {
|
|
sm.mu.Lock()
|
|
for _, scheme := range src.Schemes() {
|
|
sm.schemes[scheme] = src
|
|
}
|
|
sm.mu.Unlock()
|
|
}
|
|
|
|
func (sm *Manager) Identifier(op *pb.Op_Source, platform *pb.Platform) (Identifier, error) {
|
|
scheme, ref, ok := strings.Cut(op.Source.Identifier, "://")
|
|
if !ok {
|
|
return nil, errors.Wrapf(errInvalid, "failed to parse %s", op.Source.Identifier)
|
|
}
|
|
|
|
sm.mu.Lock()
|
|
source, found := sm.schemes[scheme]
|
|
sm.mu.Unlock()
|
|
|
|
if !found {
|
|
return nil, errors.Wrapf(errNotFound, "unknown scheme %s", scheme)
|
|
}
|
|
|
|
return source.Identifier(scheme, ref, op.Source.Attrs, platform)
|
|
}
|
|
|
|
func (sm *Manager) Resolve(ctx context.Context, id Identifier, sessM *session.Manager, vtx solver.Vertex) (SourceInstance, error) {
|
|
sm.mu.Lock()
|
|
src, ok := sm.schemes[id.Scheme()]
|
|
sm.mu.Unlock()
|
|
|
|
if !ok {
|
|
return nil, errors.Errorf("no handler for %s", id.Scheme())
|
|
}
|
|
|
|
return src.Resolve(ctx, id, sessM, vtx)
|
|
}
|