source: add local file source fundamentals

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi
2017-07-11 10:12:12 -07:00
parent fed5c1d9ce
commit 5c2e675d18
21 changed files with 780 additions and 63 deletions

View File

@@ -15,6 +15,7 @@ var (
const (
DockerImageScheme = "docker-image"
GitScheme = "git"
LocalScheme = "local"
)
type Identifier interface {
@@ -33,6 +34,8 @@ func FromString(s string) (Identifier, error) {
return NewImageIdentifier(parts[1])
case GitScheme:
return NewGitIdentifier(parts[1])
case LocalScheme:
return NewLocalIdentifier(parts[1])
default:
return nil, errors.Wrapf(errNotFound, "unknown schema %s", parts[0])
}
@@ -54,6 +57,19 @@ func NewImageIdentifier(str string) (*ImageIdentifier, error) {
return &ImageIdentifier{Reference: ref}, nil
}
func (i *ImageIdentifier) ID() string {
func (_ *ImageIdentifier) ID() string {
return DockerImageScheme
}
type LocalIdentifier struct {
Name string
SessionID string
}
func NewLocalIdentifier(str string) (*LocalIdentifier, error) {
return &LocalIdentifier{Name: str}, nil
}
func (_ *LocalIdentifier) ID() string {
return LocalScheme
}

138
source/local/local.go Normal file
View File

@@ -0,0 +1,138 @@
package local
import (
"time"
"github.com/moby/buildkit/cache"
"github.com/moby/buildkit/session"
"github.com/moby/buildkit/session/filesync"
"github.com/moby/buildkit/snapshot"
"github.com/moby/buildkit/source"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
type Opt struct {
SessionManager *session.Manager
CacheAccessor cache.Accessor
}
func NewSource(opt Opt) (source.Source, error) {
ls := &localSource{
sm: opt.SessionManager,
cm: opt.CacheAccessor,
}
return ls, nil
}
type localSource struct {
sm *session.Manager
cm cache.Accessor
}
func (ls *localSource) ID() string {
return source.LocalScheme
}
func (ls *localSource) Resolve(ctx context.Context, id source.Identifier) (source.SourceInstance, error) {
localIdentifier, ok := id.(*source.LocalIdentifier)
if !ok {
return nil, errors.Errorf("invalid local identifier %v", id)
}
return &localSourceHandler{
src: *localIdentifier,
localSource: ls,
}, nil
}
type localSourceHandler struct {
src source.LocalIdentifier
*localSource
}
func (ls *localSourceHandler) CacheKey(ctx context.Context) (string, error) {
sessionID := ls.src.SessionID
if sessionID == "" {
uuid := session.FromContext(ctx)
if uuid == "" {
return "", errors.New("could not access local files without session")
}
sessionID = uuid
}
return "session:" + ls.src.Name + ":" + sessionID, nil
}
func (ls *localSourceHandler) Snapshot(ctx context.Context) (out cache.ImmutableRef, retErr error) {
uuid := session.FromContext(ctx)
if uuid == "" {
return nil, errors.New("could not access local files without session")
}
timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
caller, err := ls.sm.Get(timeoutCtx, uuid)
if err != nil {
return nil, err
}
mutable, err := ls.cm.New(ctx, nil)
if err != nil {
return nil, err
}
defer func() {
if retErr != nil && mutable != nil {
s, err := mutable.Freeze()
if err == nil {
go s.Release(context.TODO())
}
}
}()
mount, err := mutable.Mount(ctx)
if err != nil {
return nil, err
}
lm := snapshot.LocalMounter(mount)
dest, err := lm.Mount()
if err != nil {
return nil, err
}
defer func() {
if retErr != nil && lm != nil {
lm.Unmount()
}
}()
opt := filesync.FSSendRequestOpt{
IncludePatterns: nil,
OverrideExcludes: false,
DestDir: dest,
CacheUpdater: nil,
}
if err := filesync.FSSync(ctx, caller, opt); err != nil {
return nil, err
}
if err := lm.Unmount(); err != nil {
return nil, err
}
lm = nil
snap, err := mutable.ReleaseAndCommit(ctx)
if err != nil {
return nil, err
}
mutable = nil
return snap, err
}