commit
a2dcdf4277
|
@ -10,6 +10,7 @@ import (
|
|||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/locker"
|
||||
iradix "github.com/hashicorp/go-immutable-radix"
|
||||
"github.com/hashicorp/golang-lru/simplelru"
|
||||
|
@ -51,8 +52,8 @@ func ChecksumWildcard(ctx context.Context, ref cache.ImmutableRef, path string,
|
|||
return getDefaultManager().ChecksumWildcard(ctx, ref, path, followLinks)
|
||||
}
|
||||
|
||||
func GetCacheContext(ctx context.Context, md *metadata.StorageItem) (CacheContext, error) {
|
||||
return getDefaultManager().GetCacheContext(ctx, md)
|
||||
func GetCacheContext(ctx context.Context, md *metadata.StorageItem, idmap *idtools.IdentityMapping) (CacheContext, error) {
|
||||
return getDefaultManager().GetCacheContext(ctx, md, idmap)
|
||||
}
|
||||
|
||||
func SetCacheContext(ctx context.Context, md *metadata.StorageItem, cc CacheContext) error {
|
||||
|
@ -81,7 +82,7 @@ type cacheManager struct {
|
|||
}
|
||||
|
||||
func (cm *cacheManager) Checksum(ctx context.Context, ref cache.ImmutableRef, p string, followLinks bool) (digest.Digest, error) {
|
||||
cc, err := cm.GetCacheContext(ctx, ensureOriginMetadata(ref.Metadata()))
|
||||
cc, err := cm.GetCacheContext(ctx, ensureOriginMetadata(ref.Metadata()), ref.IdentityMapping())
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
@ -89,14 +90,14 @@ func (cm *cacheManager) Checksum(ctx context.Context, ref cache.ImmutableRef, p
|
|||
}
|
||||
|
||||
func (cm *cacheManager) ChecksumWildcard(ctx context.Context, ref cache.ImmutableRef, p string, followLinks bool) (digest.Digest, error) {
|
||||
cc, err := cm.GetCacheContext(ctx, ensureOriginMetadata(ref.Metadata()))
|
||||
cc, err := cm.GetCacheContext(ctx, ensureOriginMetadata(ref.Metadata()), ref.IdentityMapping())
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
return cc.ChecksumWildcard(ctx, ref, p, followLinks)
|
||||
}
|
||||
|
||||
func (cm *cacheManager) GetCacheContext(ctx context.Context, md *metadata.StorageItem) (CacheContext, error) {
|
||||
func (cm *cacheManager) GetCacheContext(ctx context.Context, md *metadata.StorageItem, idmap *idtools.IdentityMapping) (CacheContext, error) {
|
||||
cm.locker.Lock(md.ID())
|
||||
cm.lruMu.Lock()
|
||||
v, ok := cm.lru.Get(md.ID())
|
||||
|
@ -106,7 +107,7 @@ func (cm *cacheManager) GetCacheContext(ctx context.Context, md *metadata.Storag
|
|||
v.(*cacheContext).linkMap = map[string][][]byte{}
|
||||
return v.(*cacheContext), nil
|
||||
}
|
||||
cc, err := newCacheContext(md)
|
||||
cc, err := newCacheContext(md, idmap)
|
||||
if err != nil {
|
||||
cm.locker.Unlock(md.ID())
|
||||
return nil, err
|
||||
|
@ -152,6 +153,7 @@ type cacheContext struct {
|
|||
node *iradix.Node
|
||||
dirtyMap map[string]struct{}
|
||||
linkMap map[string][][]byte
|
||||
idmap *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
type mount struct {
|
||||
|
@ -191,12 +193,13 @@ func (m *mount) clean() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func newCacheContext(md *metadata.StorageItem) (*cacheContext, error) {
|
||||
func newCacheContext(md *metadata.StorageItem, idmap *idtools.IdentityMapping) (*cacheContext, error) {
|
||||
cc := &cacheContext{
|
||||
md: md,
|
||||
tree: iradix.New(),
|
||||
dirtyMap: map[string]struct{}{},
|
||||
linkMap: map[string][][]byte{},
|
||||
idmap: idmap,
|
||||
}
|
||||
if err := cc.load(); err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -49,7 +49,7 @@ func TestChecksumHardlinks(t *testing.T) {
|
|||
|
||||
ref := createRef(t, cm, ch)
|
||||
|
||||
cc, err := newCacheContext(ref.Metadata())
|
||||
cc, err := newCacheContext(ref.Metadata(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err := cc.Checksum(context.TODO(), ref, "abc/foo", false)
|
||||
|
@ -67,7 +67,7 @@ func TestChecksumHardlinks(t *testing.T) {
|
|||
// validate same results with handleChange
|
||||
ref2 := createRef(t, cm, nil)
|
||||
|
||||
cc2, err := newCacheContext(ref2.Metadata())
|
||||
cc2, err := newCacheContext(ref2.Metadata(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = emit(cc2.HandleChange, changeStream(ch))
|
||||
|
@ -138,7 +138,7 @@ func TestChecksumWildcard(t *testing.T) {
|
|||
|
||||
ref := createRef(t, cm, ch)
|
||||
|
||||
cc, err := newCacheContext(ref.Metadata())
|
||||
cc, err := newCacheContext(ref.Metadata(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err := cc.ChecksumWildcard(context.TODO(), ref, "f*o", false)
|
||||
|
@ -189,7 +189,7 @@ func TestSymlinksNoFollow(t *testing.T) {
|
|||
|
||||
ref := createRef(t, cm, ch)
|
||||
|
||||
cc, err := newCacheContext(ref.Metadata())
|
||||
cc, err := newCacheContext(ref.Metadata(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedSym := digest.Digest("sha256:a2ba571981f48ec34eb79c9a3ab091b6491e825c2f7e9914ea86e8e958be7fae")
|
||||
|
@ -251,7 +251,7 @@ func TestChecksumBasicFile(t *testing.T) {
|
|||
// for the digest values, the actual values are not important in development
|
||||
// phase but consistency is
|
||||
|
||||
cc, err := newCacheContext(ref.Metadata())
|
||||
cc, err := newCacheContext(ref.Metadata(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = cc.Checksum(context.TODO(), ref, "nosuch", true)
|
||||
|
@ -312,7 +312,7 @@ func TestChecksumBasicFile(t *testing.T) {
|
|||
|
||||
ref = createRef(t, cm, ch)
|
||||
|
||||
cc, err = newCacheContext(ref.Metadata())
|
||||
cc, err = newCacheContext(ref.Metadata(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "/", true)
|
||||
|
@ -331,7 +331,7 @@ func TestChecksumBasicFile(t *testing.T) {
|
|||
|
||||
ref = createRef(t, cm, ch)
|
||||
|
||||
cc, err = newCacheContext(ref.Metadata())
|
||||
cc, err = newCacheContext(ref.Metadata(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "/", true)
|
||||
|
@ -357,7 +357,7 @@ func TestChecksumBasicFile(t *testing.T) {
|
|||
|
||||
ref = createRef(t, cm, ch)
|
||||
|
||||
cc, err = newCacheContext(ref.Metadata())
|
||||
cc, err = newCacheContext(ref.Metadata(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "abc/aa/foo", true)
|
||||
|
@ -401,7 +401,7 @@ func TestHandleChange(t *testing.T) {
|
|||
// for the digest values, the actual values are not important in development
|
||||
// phase but consistency is
|
||||
|
||||
cc, err := newCacheContext(ref.Metadata())
|
||||
cc, err := newCacheContext(ref.Metadata(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = emit(cc.HandleChange, changeStream(ch))
|
||||
|
@ -477,7 +477,7 @@ func TestHandleRecursiveDir(t *testing.T) {
|
|||
|
||||
ref := createRef(t, cm, nil)
|
||||
|
||||
cc, err := newCacheContext(ref.Metadata())
|
||||
cc, err := newCacheContext(ref.Metadata(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = emit(cc.HandleChange, changeStream(ch))
|
||||
|
@ -524,7 +524,7 @@ func TestChecksumUnorderedFiles(t *testing.T) {
|
|||
|
||||
ref := createRef(t, cm, nil)
|
||||
|
||||
cc, err := newCacheContext(ref.Metadata())
|
||||
cc, err := newCacheContext(ref.Metadata(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = emit(cc.HandleChange, changeStream(ch))
|
||||
|
@ -544,7 +544,7 @@ func TestChecksumUnorderedFiles(t *testing.T) {
|
|||
|
||||
ref = createRef(t, cm, nil)
|
||||
|
||||
cc, err = newCacheContext(ref.Metadata())
|
||||
cc, err = newCacheContext(ref.Metadata(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = emit(cc.HandleChange, changeStream(ch))
|
||||
|
@ -731,7 +731,7 @@ func TestSymlinkInPathHandleChange(t *testing.T) {
|
|||
|
||||
ref := createRef(t, cm, nil)
|
||||
|
||||
cc, err := newCacheContext(ref.Metadata())
|
||||
cc, err := newCacheContext(ref.Metadata(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = emit(cc.HandleChange, changeStream(ch))
|
||||
|
@ -848,7 +848,7 @@ func setupCacheManager(t *testing.T, tmpdir string, snapshotter snapshots.Snapsh
|
|||
require.NoError(t, err)
|
||||
|
||||
cm, err := cache.NewManager(cache.ManagerOpt{
|
||||
Snapshotter: snapshot.FromContainerdSnapshotter(snapshotter),
|
||||
Snapshotter: snapshot.FromContainerdSnapshotter(snapshotter, nil),
|
||||
MetadataStore: md,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/containerd/containerd/filters"
|
||||
"github.com/containerd/containerd/snapshots"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/moby/buildkit/cache/metadata"
|
||||
"github.com/moby/buildkit/client"
|
||||
"github.com/moby/buildkit/identity"
|
||||
|
@ -34,6 +35,7 @@ type Accessor interface {
|
|||
GetFromSnapshotter(ctx context.Context, id string, opts ...RefOption) (ImmutableRef, error)
|
||||
New(ctx context.Context, s ImmutableRef, opts ...RefOption) (MutableRef, error)
|
||||
GetMutable(ctx context.Context, id string) (MutableRef, error) // Rebase?
|
||||
IdentityMapping() *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
type Controller interface {
|
||||
|
@ -96,6 +98,11 @@ func (cm *cacheManager) init(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// IdentityMapping returns the userns remapping used for refs
|
||||
func (cm *cacheManager) IdentityMapping() *idtools.IdentityMapping {
|
||||
return cm.Snapshotter.IdentityMapping()
|
||||
}
|
||||
|
||||
// Close closes the manager and releases the metadata database lock. No other
|
||||
// method should be called after Close.
|
||||
func (cm *cacheManager) Close() error {
|
||||
|
|
|
@ -374,7 +374,7 @@ func getCacheManager(t *testing.T, tmpdir string, snapshotter snapshots.Snapshot
|
|||
require.NoError(t, err)
|
||||
|
||||
cm, err := NewManager(ManagerOpt{
|
||||
Snapshotter: snapshot.FromContainerdSnapshotter(snapshotter),
|
||||
Snapshotter: snapshot.FromContainerdSnapshotter(snapshotter, nil),
|
||||
MetadataStore: md,
|
||||
})
|
||||
require.NoError(t, err, fmt.Sprintf("error: %+v", err))
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/containerd/containerd/mount"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/moby/buildkit/cache/metadata"
|
||||
"github.com/moby/buildkit/identity"
|
||||
"github.com/moby/buildkit/snapshot"
|
||||
|
@ -20,6 +21,7 @@ type Ref interface {
|
|||
Release(context.Context) error
|
||||
Size(ctx context.Context) (int64, error)
|
||||
Metadata() *metadata.StorageItem
|
||||
IdentityMapping() *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
type ImmutableRef interface {
|
||||
|
@ -83,6 +85,10 @@ func (cr *cacheRecord) isDead() bool {
|
|||
return cr.dead || (cr.equalImmutable != nil && cr.equalImmutable.dead) || (cr.equalMutable != nil && cr.equalMutable.dead)
|
||||
}
|
||||
|
||||
func (cr *cacheRecord) IdentityMapping() *idtools.IdentityMapping {
|
||||
return cr.cm.IdentityMapping()
|
||||
}
|
||||
|
||||
func (cr *cacheRecord) Size(ctx context.Context) (int64, error) {
|
||||
// this expects that usage() is implemented lazily
|
||||
s, err := cr.sizeG.Do(ctx, cr.ID(), func(ctx context.Context) (interface{}, error) {
|
||||
|
|
|
@ -64,6 +64,9 @@ type OCIConfig struct {
|
|||
Rootless bool `toml:"rootless"`
|
||||
NoProcessSandbox bool `toml:"noProcessSandbox"`
|
||||
GCConfig
|
||||
// UserRemapUnsupported is unsupported key for testing. The feature is
|
||||
// incomplete and the intention is to make it default without config.
|
||||
UserRemapUnsupported string `toml:"userRemapUnsupported"`
|
||||
}
|
||||
|
||||
type ContainerdConfig struct {
|
||||
|
|
|
@ -168,6 +168,12 @@ func ociWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// TODO: this should never change the existing state dir
|
||||
idmapping, err := parseIdentityMapping(cfg.UserRemapUnsupported)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
snFactory, err := snapshotterFactory(common.config.Root, cfg.Snapshotter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -186,7 +192,7 @@ func ociWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker
|
|||
processMode = oci.NoProcessSandbox
|
||||
}
|
||||
|
||||
opt, err := runc.NewWorkerOpt(common.config.Root, snFactory, cfg.Rootless, processMode, cfg.Labels)
|
||||
opt, err := runc.NewWorkerOpt(common.config.Root, snFactory, cfg.Rootless, processMode, cfg.Labels, idmapping)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// parseBoolOrAuto returns (nil, nil) if s is "auto"
|
||||
|
@ -13,3 +18,32 @@ func parseBoolOrAuto(s string) (*bool, error) {
|
|||
b, err := strconv.ParseBool(s)
|
||||
return &b, err
|
||||
}
|
||||
|
||||
func parseIdentityMapping(str string) (*idtools.IdentityMapping, error) {
|
||||
if str == "" {
|
||||
return nil, nil
|
||||
}
|
||||
if runtime.GOOS != "linux" && str != "" {
|
||||
return nil, errors.Errorf("user namespaces are only supported on linux")
|
||||
}
|
||||
|
||||
idparts := strings.Split(str, ":")
|
||||
if len(idparts) > 2 {
|
||||
return nil, errors.Errorf("invalid userns remap specification in %q", str)
|
||||
}
|
||||
|
||||
username := idparts[0]
|
||||
groupname := username
|
||||
if len(idparts) == 2 {
|
||||
groupname = idparts[1]
|
||||
}
|
||||
|
||||
logrus.Debugf("user namespaces: ID ranges will be mapped to subuid/subgid ranges of: %s:%s", username, groupname)
|
||||
|
||||
mappings, err := idtools.NewIdentityMapping(username, groupname)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create ID mappings")
|
||||
}
|
||||
return mappings, nil
|
||||
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ func (w containerdExecutor) Exec(ctx context.Context, meta executor.Meta, root c
|
|||
opts = append(opts, containerdoci.WithCgroup(cgroupsPath))
|
||||
}
|
||||
processMode := oci.ProcessSandbox // FIXME(AkihiroSuda)
|
||||
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, processMode, opts...)
|
||||
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, processMode, nil, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/containerd/containerd/namespaces"
|
||||
"github.com/containerd/containerd/oci"
|
||||
"github.com/containerd/continuity/fs"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/mitchellh/hashstructure"
|
||||
"github.com/moby/buildkit/executor"
|
||||
"github.com/moby/buildkit/snapshot"
|
||||
|
@ -40,7 +41,7 @@ const (
|
|||
|
||||
// GenerateSpec generates spec using containerd functionality.
|
||||
// opts are ignored for s.Process, s.Hostname, and s.Mounts .
|
||||
func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, namespace network.Namespace, processMode ProcessMode, opts ...oci.SpecOpts) (*specs.Spec, func(), error) {
|
||||
func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, namespace network.Namespace, processMode ProcessMode, idmap *idtools.IdentityMapping, opts ...oci.SpecOpts) (*specs.Spec, func(), error) {
|
||||
c := &containers.Container{
|
||||
ID: id,
|
||||
}
|
||||
|
@ -102,7 +103,14 @@ func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mou
|
|||
}
|
||||
}
|
||||
}
|
||||
// TODO: User
|
||||
|
||||
if idmap != nil {
|
||||
s.Linux.Namespaces = append(s.Linux.Namespaces, specs.LinuxNamespace{
|
||||
Type: specs.UserNamespace,
|
||||
})
|
||||
s.Linux.UIDMappings = specMapping(idmap.UIDs())
|
||||
s.Linux.GIDMappings = specMapping(idmap.GIDs())
|
||||
}
|
||||
|
||||
sm := &submounts{}
|
||||
|
||||
|
@ -227,3 +235,15 @@ func sub(m mount.Mount, subPath string) (mount.Mount, error) {
|
|||
m.Source = src
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func specMapping(s []idtools.IDMap) []specs.LinuxIDMapping {
|
||||
var ids []specs.LinuxIDMapping
|
||||
for _, item := range s {
|
||||
ids = append(ids, specs.LinuxIDMapping{
|
||||
HostID: uint32(item.HostID),
|
||||
ContainerID: uint32(item.ContainerID),
|
||||
Size: uint32(item.Size),
|
||||
})
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
containerdoci "github.com/containerd/containerd/oci"
|
||||
"github.com/containerd/continuity/fs"
|
||||
runc "github.com/containerd/go-runc"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/moby/buildkit/cache"
|
||||
"github.com/moby/buildkit/executor"
|
||||
"github.com/moby/buildkit/executor/oci"
|
||||
|
@ -38,7 +39,8 @@ type Opt struct {
|
|||
// DefaultCgroupParent is the cgroup-parent name for executor
|
||||
DefaultCgroupParent string
|
||||
// ProcessMode
|
||||
ProcessMode oci.ProcessMode
|
||||
ProcessMode oci.ProcessMode
|
||||
IdentityMapping *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
var defaultCommandCandidates = []string{"buildkit-runc", "runc"}
|
||||
|
@ -51,6 +53,7 @@ type runcExecutor struct {
|
|||
rootless bool
|
||||
networkProviders map[pb.NetMode]network.Provider
|
||||
processMode oci.ProcessMode
|
||||
idmap *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Executor, error) {
|
||||
|
@ -107,6 +110,7 @@ func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Ex
|
|||
rootless: opt.Rootless,
|
||||
networkProviders: networkProviders,
|
||||
processMode: opt.ProcessMode,
|
||||
idmap: opt.IdentityMapping,
|
||||
}
|
||||
return w, nil
|
||||
}
|
||||
|
@ -157,8 +161,14 @@ func (w *runcExecutor) Exec(ctx context.Context, meta executor.Meta, root cache.
|
|||
return err
|
||||
}
|
||||
defer os.RemoveAll(bundle)
|
||||
|
||||
identity := idtools.Identity{}
|
||||
if w.idmap != nil {
|
||||
identity = w.idmap.RootPair()
|
||||
}
|
||||
|
||||
rootFSPath := filepath.Join(bundle, "rootfs")
|
||||
if err := os.Mkdir(rootFSPath, 0700); err != nil {
|
||||
if err := idtools.MkdirAllAndChown(rootFSPath, 0700, identity); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := mount.All(rootMount, rootFSPath); err != nil {
|
||||
|
@ -193,7 +203,7 @@ func (w *runcExecutor) Exec(ctx context.Context, meta executor.Meta, root cache.
|
|||
}
|
||||
opts = append(opts, containerdoci.WithCgroup(cgroupsPath))
|
||||
}
|
||||
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, w.processMode, opts...)
|
||||
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, w.processMode, w.idmap, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -208,7 +218,7 @@ func (w *runcExecutor) Exec(ctx context.Context, meta executor.Meta, root cache.
|
|||
if err != nil {
|
||||
return errors.Wrapf(err, "working dir %s points to invalid target", newp)
|
||||
}
|
||||
if err := os.MkdirAll(newp, 0755); err != nil {
|
||||
if err := idtools.MkdirAllAndChown(newp, 0755, identity); err != nil {
|
||||
return errors.Wrapf(err, "failed to create working directory %s", newp)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/moby/buildkit/cache"
|
||||
"github.com/moby/buildkit/exporter"
|
||||
"github.com/moby/buildkit/session"
|
||||
|
@ -68,6 +69,7 @@ func (e *localExporterInstance) Export(ctx context.Context, inp exporter.Source)
|
|||
return func() error {
|
||||
var src string
|
||||
var err error
|
||||
var idmap *idtools.IdentityMapping
|
||||
if ref == nil {
|
||||
src, err = ioutil.TempDir("", "buildkit")
|
||||
if err != nil {
|
||||
|
@ -86,10 +88,30 @@ func (e *localExporterInstance) Export(ctx context.Context, inp exporter.Source)
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
idmap = mount.IdentityMapping()
|
||||
|
||||
defer lm.Unmount()
|
||||
}
|
||||
|
||||
fs := fsutil.NewFS(src, nil)
|
||||
walkOpt := &fsutil.WalkOpt{}
|
||||
|
||||
if idmap != nil {
|
||||
walkOpt.Map = func(p string, st *fstypes.Stat) bool {
|
||||
uid, gid, err := idmap.ToContainer(idtools.Identity{
|
||||
UID: int(st.Uid),
|
||||
GID: int(st.Gid),
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
st.Uid = uint32(uid)
|
||||
st.Gid = uint32(gid)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
fs := fsutil.NewFS(src, walkOpt)
|
||||
lbl := "copying files"
|
||||
if isMap {
|
||||
lbl += " " + k
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/moby/buildkit/cache"
|
||||
"github.com/moby/buildkit/exporter"
|
||||
"github.com/moby/buildkit/session"
|
||||
|
@ -71,6 +72,7 @@ func (e *localExporterInstance) Export(ctx context.Context, inp exporter.Source)
|
|||
getDir := func(ctx context.Context, k string, ref cache.ImmutableRef) (*fsutil.Dir, error) {
|
||||
var src string
|
||||
var err error
|
||||
var idmap *idtools.IdentityMapping
|
||||
if ref == nil {
|
||||
src, err = ioutil.TempDir("", "buildkit")
|
||||
if err != nil {
|
||||
|
@ -89,11 +91,31 @@ func (e *localExporterInstance) Export(ctx context.Context, inp exporter.Source)
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
idmap = mount.IdentityMapping()
|
||||
|
||||
defers = append(defers, func() { lm.Unmount() })
|
||||
}
|
||||
|
||||
walkOpt := &fsutil.WalkOpt{}
|
||||
|
||||
if idmap != nil {
|
||||
walkOpt.Map = func(p string, st *fstypes.Stat) bool {
|
||||
uid, gid, err := idmap.ToContainer(idtools.Identity{
|
||||
UID: int(st.Uid),
|
||||
GID: int(st.Gid),
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
st.Uid = uint32(uid)
|
||||
st.Gid = uint32(gid)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return &fsutil.Dir{
|
||||
FS: fsutil.NewFS(src, nil),
|
||||
FS: fsutil.NewFS(src, walkOpt),
|
||||
Stat: fstypes.Stat{
|
||||
Mode: uint32(os.ModeDir | 0755),
|
||||
Path: strings.Replace(k, "/", "_", -1),
|
||||
|
|
|
@ -57,7 +57,7 @@ func (wc *streamWriterCloser) Close() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func recvDiffCopy(ds grpc.Stream, dest string, cu CacheUpdater, progress progressCb) error {
|
||||
func recvDiffCopy(ds grpc.Stream, dest string, cu CacheUpdater, progress progressCb, filter func(string, *fstypes.Stat) bool) error {
|
||||
st := time.Now()
|
||||
defer func() {
|
||||
logrus.Debugf("diffcopy took: %v", time.Since(st))
|
||||
|
@ -73,6 +73,7 @@ func recvDiffCopy(ds grpc.Stream, dest string, cu CacheUpdater, progress progres
|
|||
NotifyHashed: cf,
|
||||
ContentHasher: ch,
|
||||
ProgressCb: progress,
|
||||
Filter: fsutil.FilterFunc(filter),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ type progressCb func(int, bool)
|
|||
type protocol struct {
|
||||
name string
|
||||
sendFn func(stream grpc.Stream, fs fsutil.FS, progress progressCb) error
|
||||
recvFn func(stream grpc.Stream, destDir string, cu CacheUpdater, progress progressCb) error
|
||||
recvFn func(stream grpc.Stream, destDir string, cu CacheUpdater, progress progressCb, mapFunc func(string, *fstypes.Stat) bool) error
|
||||
}
|
||||
|
||||
func isProtoSupported(p string) bool {
|
||||
|
@ -158,6 +158,7 @@ type FSSendRequestOpt struct {
|
|||
DestDir string
|
||||
CacheUpdater CacheUpdater
|
||||
ProgressCb func(int, bool)
|
||||
Filter func(string, *fstypes.Stat) bool
|
||||
}
|
||||
|
||||
// CacheUpdater is an object capable of sending notifications for the cache hash changes
|
||||
|
@ -225,7 +226,7 @@ func FSSync(ctx context.Context, c session.Caller, opt FSSendRequestOpt) error {
|
|||
panic(fmt.Sprintf("invalid protocol: %q", pr.name))
|
||||
}
|
||||
|
||||
return pr.recvFn(stream, opt.DestDir, opt.CacheUpdater, opt.ProgressCb)
|
||||
return pr.recvFn(stream, opt.DestDir, opt.CacheUpdater, opt.ProgressCb, opt.Filter)
|
||||
}
|
||||
|
||||
// NewFSSyncTargetDir allows writing into a directory
|
||||
|
|
|
@ -8,15 +8,16 @@ import (
|
|||
"github.com/containerd/containerd/mount"
|
||||
"github.com/containerd/containerd/namespaces"
|
||||
ctdsnapshot "github.com/containerd/containerd/snapshots"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/moby/buildkit/cache/metadata"
|
||||
"github.com/moby/buildkit/snapshot"
|
||||
"github.com/moby/buildkit/snapshot/blobmapping"
|
||||
)
|
||||
|
||||
func NewSnapshotter(snapshotter ctdsnapshot.Snapshotter, store content.Store, mdstore *metadata.Store, ns string, gc func(context.Context) error) snapshot.Snapshotter {
|
||||
func NewSnapshotter(snapshotter ctdsnapshot.Snapshotter, store content.Store, mdstore *metadata.Store, ns string, gc func(context.Context) error, idmap *idtools.IdentityMapping) snapshot.Snapshotter {
|
||||
return blobmapping.NewSnapshotter(blobmapping.Opt{
|
||||
Content: store,
|
||||
Snapshotter: snapshot.FromContainerdSnapshotter(&nsSnapshotter{ns, snapshotter, gc}),
|
||||
Snapshotter: snapshot.FromContainerdSnapshotter(&nsSnapshotter{ns, snapshotter, gc}, idmap),
|
||||
MetadataStore: mdstore,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/containerd/containerd/mount"
|
||||
"github.com/containerd/containerd/snapshots"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
|
@ -13,6 +14,7 @@ type Mountable interface {
|
|||
// ID() string
|
||||
Mount() ([]mount.Mount, error)
|
||||
Release() error
|
||||
IdentityMapping() *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
type SnapshotterBase interface {
|
||||
|
@ -27,6 +29,7 @@ type SnapshotterBase interface {
|
|||
Remove(ctx context.Context, key string) error
|
||||
Walk(ctx context.Context, fn func(context.Context, snapshots.Info) error) error
|
||||
Close() error
|
||||
IdentityMapping() *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
// Snapshotter defines interface that any snapshot implementation should satisfy
|
||||
|
@ -40,12 +43,13 @@ type Blobmapper interface {
|
|||
SetBlob(ctx context.Context, key string, diffID, blob digest.Digest) error
|
||||
}
|
||||
|
||||
func FromContainerdSnapshotter(s snapshots.Snapshotter) SnapshotterBase {
|
||||
return &fromContainerd{Snapshotter: s}
|
||||
func FromContainerdSnapshotter(s snapshots.Snapshotter, idmap *idtools.IdentityMapping) SnapshotterBase {
|
||||
return &fromContainerd{Snapshotter: s, idmap: idmap}
|
||||
}
|
||||
|
||||
type fromContainerd struct {
|
||||
snapshots.Snapshotter
|
||||
idmap *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
func (s *fromContainerd) Mounts(ctx context.Context, key string) (Mountable, error) {
|
||||
|
@ -53,7 +57,7 @@ func (s *fromContainerd) Mounts(ctx context.Context, key string) (Mountable, err
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &staticMountable{mounts}, nil
|
||||
return &staticMountable{mounts, s.idmap}, nil
|
||||
}
|
||||
func (s *fromContainerd) Prepare(ctx context.Context, key, parent string, opts ...snapshots.Opt) error {
|
||||
_, err := s.Snapshotter.Prepare(ctx, key, parent, opts...)
|
||||
|
@ -64,11 +68,15 @@ func (s *fromContainerd) View(ctx context.Context, key, parent string, opts ...s
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &staticMountable{mounts}, nil
|
||||
return &staticMountable{mounts, s.idmap}, nil
|
||||
}
|
||||
func (s *fromContainerd) IdentityMapping() *idtools.IdentityMapping {
|
||||
return s.idmap
|
||||
}
|
||||
|
||||
type staticMountable struct {
|
||||
mounts []mount.Mount
|
||||
idmap *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
func (m *staticMountable) Mount() ([]mount.Mount, error) {
|
||||
|
@ -79,6 +87,10 @@ func (cm *staticMountable) Release() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (cm *staticMountable) IdentityMapping() *idtools.IdentityMapping {
|
||||
return cm.idmap
|
||||
}
|
||||
|
||||
// NewContainerdSnapshotter converts snapshotter to containerd snapshotter
|
||||
func NewContainerdSnapshotter(s Snapshotter) (snapshots.Snapshotter, func() error) {
|
||||
cs := &containerdSnapshotter{Snapshotter: s}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/containerd/continuity/fs"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/moby/buildkit/snapshot"
|
||||
"github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes"
|
||||
"github.com/moby/buildkit/solver/pb"
|
||||
|
@ -25,12 +26,35 @@ func timestampToTime(ts int64) *time.Time {
|
|||
return &tm
|
||||
}
|
||||
|
||||
func mkdir(ctx context.Context, d string, action pb.FileActionMkDir, user *copy.ChownOpt) error {
|
||||
func mapUser(user *copy.ChownOpt, idmap *idtools.IdentityMapping) (*copy.ChownOpt, error) {
|
||||
if idmap == nil {
|
||||
return user, nil
|
||||
}
|
||||
if user == nil {
|
||||
identity := idmap.RootPair()
|
||||
return ©.ChownOpt{Uid: identity.UID, Gid: identity.GID}, nil
|
||||
}
|
||||
identity, err := idmap.ToHost(idtools.Identity{
|
||||
UID: user.Uid,
|
||||
GID: user.Gid,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ©.ChownOpt{Uid: identity.UID, Gid: identity.GID}, nil
|
||||
}
|
||||
|
||||
func mkdir(ctx context.Context, d string, action pb.FileActionMkDir, user *copy.ChownOpt, idmap *idtools.IdentityMapping) error {
|
||||
p, err := fs.RootPath(d, filepath.Join(filepath.Join("/", action.Path)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user, err = mapUser(user, idmap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if action.MakeParents {
|
||||
if err := copy.MkdirAll(p, os.FileMode(action.Mode)&0777, user, timestampToTime(action.Timestamp)); err != nil {
|
||||
return err
|
||||
|
@ -53,12 +77,17 @@ func mkdir(ctx context.Context, d string, action pb.FileActionMkDir, user *copy.
|
|||
return nil
|
||||
}
|
||||
|
||||
func mkfile(ctx context.Context, d string, action pb.FileActionMkFile, user *copy.ChownOpt) error {
|
||||
func mkfile(ctx context.Context, d string, action pb.FileActionMkFile, user *copy.ChownOpt, idmap *idtools.IdentityMapping) error {
|
||||
p, err := fs.RootPath(d, filepath.Join(filepath.Join("/", action.Path)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user, err = mapUser(user, idmap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(p, action.Data, os.FileMode(action.Mode)&0777); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -90,7 +119,7 @@ func rm(ctx context.Context, d string, action pb.FileActionRm) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *copy.ChownOpt) error {
|
||||
func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *copy.ChownOpt, idmap *idtools.IdentityMapping) error {
|
||||
srcPath := cleanPath(action.Src)
|
||||
destPath := cleanPath(action.Dest)
|
||||
|
||||
|
@ -109,6 +138,12 @@ func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *
|
|||
return nil
|
||||
}
|
||||
|
||||
// TODO(tonistiigi): this is wrong. fsutil.Copy can't handle non-forced user
|
||||
u, err := mapUser(u, idmap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
opt := []copy.Opt{
|
||||
func(ci *copy.CopyInfo) {
|
||||
ci.Chown = u
|
||||
|
@ -195,7 +230,7 @@ func (fb *Backend) Mkdir(ctx context.Context, m, user, group fileoptypes.Mount,
|
|||
return err
|
||||
}
|
||||
|
||||
return mkdir(ctx, dir, action, u)
|
||||
return mkdir(ctx, dir, action, u, mnt.m.IdentityMapping())
|
||||
}
|
||||
|
||||
func (fb *Backend) Mkfile(ctx context.Context, m, user, group fileoptypes.Mount, action pb.FileActionMkFile) error {
|
||||
|
@ -216,7 +251,7 @@ func (fb *Backend) Mkfile(ctx context.Context, m, user, group fileoptypes.Mount,
|
|||
return err
|
||||
}
|
||||
|
||||
return mkfile(ctx, dir, action, u)
|
||||
return mkfile(ctx, dir, action, u, mnt.m.IdentityMapping())
|
||||
}
|
||||
func (fb *Backend) Rm(ctx context.Context, m fileoptypes.Mount, action pb.FileActionRm) error {
|
||||
mnt, ok := m.(*Mount)
|
||||
|
@ -262,5 +297,5 @@ func (fb *Backend) Copy(ctx context.Context, m1, m2, user, group fileoptypes.Mou
|
|||
return err
|
||||
}
|
||||
|
||||
return docopy(ctx, src, dest, action, u)
|
||||
return docopy(ctx, src, dest, action, u, mnt2.m.IdentityMapping())
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
|
||||
"github.com/containerd/containerd/mount"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/locker"
|
||||
"github.com/moby/buildkit/cache"
|
||||
"github.com/moby/buildkit/cache/metadata"
|
||||
|
@ -329,30 +330,47 @@ func (e *execOp) getSSHMountable(ctx context.Context, m *pb.Mount) (cache.Mounta
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &sshMount{mount: m, caller: caller}, nil
|
||||
return &sshMount{mount: m, caller: caller, idmap: e.cm.IdentityMapping()}, nil
|
||||
}
|
||||
|
||||
type sshMount struct {
|
||||
mount *pb.Mount
|
||||
caller session.Caller
|
||||
idmap *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
func (sm *sshMount) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
|
||||
return &sshMountInstance{sm: sm}, nil
|
||||
return &sshMountInstance{sm: sm, idmap: sm.idmap}, nil
|
||||
}
|
||||
|
||||
type sshMountInstance struct {
|
||||
sm *sshMount
|
||||
cleanup func() error
|
||||
idmap *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
func (sm *sshMountInstance) Mount() ([]mount.Mount, error) {
|
||||
ctx, cancel := context.WithCancel(context.TODO())
|
||||
|
||||
uid := int(sm.sm.mount.SSHOpt.Uid)
|
||||
gid := int(sm.sm.mount.SSHOpt.Gid)
|
||||
|
||||
if sm.idmap != nil {
|
||||
identity, err := sm.idmap.ToHost(idtools.Identity{
|
||||
UID: uid,
|
||||
GID: gid,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uid = identity.UID
|
||||
gid = identity.GID
|
||||
}
|
||||
|
||||
sock, cleanup, err := sshforward.MountSSHSocket(ctx, sm.sm.caller, sshforward.SocketOpt{
|
||||
ID: sm.sm.mount.SSHOpt.ID,
|
||||
UID: int(sm.sm.mount.SSHOpt.Uid),
|
||||
GID: int(sm.sm.mount.SSHOpt.Gid),
|
||||
UID: uid,
|
||||
GID: gid,
|
||||
Mode: int(sm.sm.mount.SSHOpt.Mode & 0777),
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -384,6 +402,10 @@ func (sm *sshMountInstance) Release() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (sm *sshMountInstance) IdentityMapping() *idtools.IdentityMapping {
|
||||
return sm.idmap
|
||||
}
|
||||
|
||||
func (e *execOp) getSecretMountable(ctx context.Context, m *pb.Mount) (cache.Mountable, error) {
|
||||
if m.SecretOpt == nil {
|
||||
return nil, errors.Errorf("invalid sercet mount options")
|
||||
|
@ -416,21 +438,23 @@ func (e *execOp) getSecretMountable(ctx context.Context, m *pb.Mount) (cache.Mou
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &secretMount{mount: m, data: dt}, nil
|
||||
return &secretMount{mount: m, data: dt, idmap: e.cm.IdentityMapping()}, nil
|
||||
}
|
||||
|
||||
type secretMount struct {
|
||||
mount *pb.Mount
|
||||
data []byte
|
||||
idmap *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
func (sm *secretMount) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
|
||||
return &secretMountInstance{sm: sm}, nil
|
||||
return &secretMountInstance{sm: sm, idmap: sm.idmap}, nil
|
||||
}
|
||||
|
||||
type secretMountInstance struct {
|
||||
sm *secretMount
|
||||
root string
|
||||
sm *secretMount
|
||||
root string
|
||||
idmap *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
func (sm *secretMountInstance) Mount() ([]mount.Mount, error) {
|
||||
|
@ -465,7 +489,22 @@ func (sm *secretMountInstance) Mount() ([]mount.Mount, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if err := os.Chown(fp, int(sm.sm.mount.SecretOpt.Uid), int(sm.sm.mount.SecretOpt.Gid)); err != nil {
|
||||
uid := int(sm.sm.mount.SecretOpt.Uid)
|
||||
gid := int(sm.sm.mount.SecretOpt.Gid)
|
||||
|
||||
if sm.idmap != nil {
|
||||
identity, err := sm.idmap.ToHost(idtools.Identity{
|
||||
UID: uid,
|
||||
GID: gid,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uid = identity.UID
|
||||
gid = identity.GID
|
||||
}
|
||||
|
||||
if err := os.Chown(fp, uid, gid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -490,6 +529,10 @@ func (sm *secretMountInstance) Release() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (sm *secretMountInstance) IdentityMapping() *idtools.IdentityMapping {
|
||||
return sm.idmap
|
||||
}
|
||||
|
||||
func addDefaultEnvvar(env []string, k, v string) []string {
|
||||
for _, e := range env {
|
||||
if strings.HasPrefix(e, k+"=") {
|
||||
|
@ -585,7 +628,7 @@ func (e *execOp) Exec(ctx context.Context, inputs []solver.Result) ([]solver.Res
|
|||
}
|
||||
|
||||
case pb.MountType_TMPFS:
|
||||
mountable = newTmpfs()
|
||||
mountable = newTmpfs(e.cm.IdentityMapping())
|
||||
|
||||
case pb.MountType_SECRET:
|
||||
secretMount, err := e.getSecretMountable(ctx, m)
|
||||
|
@ -702,19 +745,21 @@ func proxyEnvList(p *pb.ProxyEnv) []string {
|
|||
return out
|
||||
}
|
||||
|
||||
func newTmpfs() cache.Mountable {
|
||||
return &tmpfs{}
|
||||
func newTmpfs(idmap *idtools.IdentityMapping) cache.Mountable {
|
||||
return &tmpfs{idmap: idmap}
|
||||
}
|
||||
|
||||
type tmpfs struct {
|
||||
idmap *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
func (f *tmpfs) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
|
||||
return &tmpfsMount{readonly: readonly}, nil
|
||||
return &tmpfsMount{readonly: readonly, idmap: f.idmap}, nil
|
||||
}
|
||||
|
||||
type tmpfsMount struct {
|
||||
readonly bool
|
||||
idmap *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
func (m *tmpfsMount) Mount() ([]mount.Mount, error) {
|
||||
|
@ -732,6 +777,10 @@ func (m *tmpfsMount) Release() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *tmpfsMount) IdentityMapping() *idtools.IdentityMapping {
|
||||
return m.idmap
|
||||
}
|
||||
|
||||
var cacheRefsLocker = locker.New()
|
||||
var sharedCacheRefs = &cacheRefs{}
|
||||
|
||||
|
|
|
@ -335,6 +335,16 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context) (out cache.ImmutableRe
|
|||
return nil, errors.Wrapf(err, "failed to update submodules for %s", gs.src.Remote)
|
||||
}
|
||||
|
||||
if idmap := mount.IdentityMapping(); idmap != nil {
|
||||
u := idmap.RootPair()
|
||||
err := filepath.Walk(gitDir, func(p string, f os.FileInfo, err error) error {
|
||||
return os.Lchown(p, u.UID, u.GID)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to remap git checkout")
|
||||
}
|
||||
}
|
||||
|
||||
lm.Unmount()
|
||||
lm = nil
|
||||
|
||||
|
|
|
@ -297,7 +297,7 @@ func setupGitSource(t *testing.T, tmpdir string) source.Source {
|
|||
assert.NoError(t, err)
|
||||
|
||||
cm, err := cache.NewManager(cache.ManagerOpt{
|
||||
Snapshotter: snapshot.FromContainerdSnapshotter(snapshotter),
|
||||
Snapshotter: snapshot.FromContainerdSnapshotter(snapshotter, nil),
|
||||
MetadataStore: md,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/locker"
|
||||
"github.com/moby/buildkit/cache"
|
||||
"github.com/moby/buildkit/cache/metadata"
|
||||
|
@ -278,8 +279,22 @@ func (hs *httpSourceHandler) save(ctx context.Context, resp *http.Response) (ref
|
|||
}
|
||||
f = nil
|
||||
|
||||
if hs.src.UID != 0 || hs.src.GID != 0 {
|
||||
if err := os.Chown(fp, hs.src.UID, hs.src.GID); err != nil {
|
||||
uid := hs.src.UID
|
||||
gid := hs.src.GID
|
||||
if idmap := mount.IdentityMapping(); idmap != nil {
|
||||
identity, err := idmap.ToHost(idtools.Identity{
|
||||
UID: int(uid),
|
||||
GID: int(gid),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
uid = identity.UID
|
||||
gid = identity.GID
|
||||
}
|
||||
|
||||
if gid != 0 || uid != 0 {
|
||||
if err := os.Chown(fp, uid, gid); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -315,7 +315,7 @@ func newHTTPSource(tmpdir string) (source.Source, error) {
|
|||
}
|
||||
|
||||
cm, err := cache.NewManager(cache.ManagerOpt{
|
||||
Snapshotter: snapshot.FromContainerdSnapshotter(snapshotter),
|
||||
Snapshotter: snapshot.FromContainerdSnapshotter(snapshotter, nil),
|
||||
MetadataStore: md,
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/moby/buildkit/cache"
|
||||
"github.com/moby/buildkit/cache/contenthash"
|
||||
"github.com/moby/buildkit/cache/metadata"
|
||||
|
@ -19,6 +20,7 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/tonistiigi/fsutil"
|
||||
fstypes "github.com/tonistiigi/fsutil/types"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"golang.org/x/time/rate"
|
||||
"google.golang.org/grpc/codes"
|
||||
|
@ -153,7 +155,7 @@ func (ls *localSourceHandler) Snapshot(ctx context.Context) (out cache.Immutable
|
|||
}
|
||||
}()
|
||||
|
||||
cc, err := contenthash.GetCacheContext(ctx, mutable.Metadata())
|
||||
cc, err := contenthash.GetCacheContext(ctx, mutable.Metadata(), mount.IdentityMapping())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -165,10 +167,25 @@ func (ls *localSourceHandler) Snapshot(ctx context.Context) (out cache.Immutable
|
|||
FollowPaths: ls.src.FollowPaths,
|
||||
OverrideExcludes: false,
|
||||
DestDir: dest,
|
||||
CacheUpdater: &cacheUpdater{cc},
|
||||
CacheUpdater: &cacheUpdater{cc, mount.IdentityMapping()},
|
||||
ProgressCb: newProgressHandler(ctx, "transferring "+ls.src.Name+":"),
|
||||
}
|
||||
|
||||
if idmap := mount.IdentityMapping(); idmap != nil {
|
||||
opt.Filter = func(p string, stat *fstypes.Stat) bool {
|
||||
identity, err := idmap.ToHost(idtools.Identity{
|
||||
UID: int(stat.Uid),
|
||||
GID: int(stat.Gid),
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
stat.Uid = uint32(identity.UID)
|
||||
stat.Gid = uint32(identity.GID)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if err := filesync.FSSync(ctx, caller, opt); err != nil {
|
||||
if status.Code(err) == codes.NotFound {
|
||||
return nil, errors.Errorf("local source %s not enabled from the client", ls.src.Name)
|
||||
|
@ -245,6 +262,7 @@ func newProgressHandler(ctx context.Context, id string) func(int, bool) {
|
|||
|
||||
type cacheUpdater struct {
|
||||
contenthash.CacheContext
|
||||
idmap *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
func (cu *cacheUpdater) MarkSupported(bool) {
|
||||
|
|
|
@ -94,9 +94,9 @@ github.com/containerd/continuity/fs
|
|||
github.com/containerd/continuity/syscallx
|
||||
github.com/containerd/continuity
|
||||
github.com/containerd/continuity/fs/fstest
|
||||
github.com/containerd/continuity/pathdriver
|
||||
github.com/containerd/continuity/devices
|
||||
github.com/containerd/continuity/driver
|
||||
github.com/containerd/continuity/pathdriver
|
||||
github.com/containerd/continuity/proto
|
||||
# github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260
|
||||
github.com/containerd/fifo
|
||||
|
@ -116,6 +116,7 @@ github.com/docker/cli/cli/config/types
|
|||
github.com/docker/distribution/reference
|
||||
github.com/docker/distribution/digestset
|
||||
# github.com/docker/docker v1.14.0-0.20190319215453-e7b5f7dbe98c
|
||||
github.com/docker/docker/pkg/idtools
|
||||
github.com/docker/docker/pkg/locker
|
||||
github.com/docker/docker/pkg/reexec
|
||||
github.com/docker/docker/builder/dockerignore
|
||||
|
@ -124,15 +125,14 @@ github.com/docker/docker/pkg/signal
|
|||
github.com/docker/docker/api/types/container
|
||||
github.com/docker/docker/pkg/archive
|
||||
github.com/docker/docker/pkg/chrootarchive
|
||||
github.com/docker/docker/pkg/system
|
||||
github.com/docker/docker/pkg/fileutils
|
||||
github.com/docker/docker/pkg/ioutils
|
||||
github.com/docker/docker/api/types/blkiodev
|
||||
github.com/docker/docker/api/types/mount
|
||||
github.com/docker/docker/pkg/homedir
|
||||
github.com/docker/docker/pkg/idtools
|
||||
github.com/docker/docker/pkg/longpath
|
||||
github.com/docker/docker/pkg/pools
|
||||
github.com/docker/docker/pkg/system
|
||||
github.com/docker/docker/pkg/mount
|
||||
# github.com/docker/docker-credential-helpers v0.6.0
|
||||
github.com/docker/docker-credential-helpers/client
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/rootfs"
|
||||
cdsnapshot "github.com/containerd/containerd/snapshots"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/moby/buildkit/cache"
|
||||
"github.com/moby/buildkit/cache/blobs"
|
||||
"github.com/moby/buildkit/cache/metadata"
|
||||
|
@ -70,6 +71,7 @@ type WorkerOpt struct {
|
|||
Differ diff.Comparer
|
||||
ImageStore images.Store // optional
|
||||
ResolveOptionsFunc resolver.ResolveOptionsFunc
|
||||
IdentityMapping *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
// Worker is a local worker instance with dedicated snapshotter, cache, and so on.
|
||||
|
|
|
@ -106,7 +106,7 @@ func newContainerd(root string, client *containerd.Client, snapshotterName, ns s
|
|||
Labels: xlabels,
|
||||
MetadataStore: md,
|
||||
Executor: containerdexecutor.New(client, root, "", network.Default()),
|
||||
Snapshotter: containerdsnapshot.NewSnapshotter(client.SnapshotService(snapshotterName), cs, md, ns, gc),
|
||||
Snapshotter: containerdsnapshot.NewSnapshotter(client.SnapshotService(snapshotterName), cs, md, ns, gc, nil),
|
||||
ContentStore: cs,
|
||||
Applier: winlayers.NewFileSystemApplierWithWindows(cs, df),
|
||||
Differ: winlayers.NewWalkingDiffWithWindows(cs, df),
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
ctdmetadata "github.com/containerd/containerd/metadata"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
ctdsnapshot "github.com/containerd/containerd/snapshots"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/moby/buildkit/cache/metadata"
|
||||
"github.com/moby/buildkit/executor/oci"
|
||||
"github.com/moby/buildkit/executor/runcexecutor"
|
||||
|
@ -32,7 +33,7 @@ type SnapshotterFactory struct {
|
|||
}
|
||||
|
||||
// NewWorkerOpt creates a WorkerOpt.
|
||||
func NewWorkerOpt(root string, snFactory SnapshotterFactory, rootless bool, processMode oci.ProcessMode, labels map[string]string) (base.WorkerOpt, error) {
|
||||
func NewWorkerOpt(root string, snFactory SnapshotterFactory, rootless bool, processMode oci.ProcessMode, labels map[string]string, idmap *idtools.IdentityMapping) (base.WorkerOpt, error) {
|
||||
var opt base.WorkerOpt
|
||||
name := "runc-" + snFactory.Name
|
||||
root = filepath.Join(root, name)
|
||||
|
@ -47,8 +48,9 @@ func NewWorkerOpt(root string, snFactory SnapshotterFactory, rootless bool, proc
|
|||
// Root directory
|
||||
Root: filepath.Join(root, "executor"),
|
||||
// without root privileges
|
||||
Rootless: rootless,
|
||||
ProcessMode: processMode,
|
||||
Rootless: rootless,
|
||||
ProcessMode: processMode,
|
||||
IdentityMapping: idmap,
|
||||
}, network.Default())
|
||||
if err != nil {
|
||||
return opt, err
|
||||
|
@ -97,16 +99,17 @@ func NewWorkerOpt(root string, snFactory SnapshotterFactory, rootless bool, proc
|
|||
xlabels[k] = v
|
||||
}
|
||||
opt = base.WorkerOpt{
|
||||
ID: id,
|
||||
Labels: xlabels,
|
||||
MetadataStore: md,
|
||||
Executor: exe,
|
||||
Snapshotter: containerdsnapshot.NewSnapshotter(mdb.Snapshotter(snFactory.Name), c, md, "buildkit", gc),
|
||||
ContentStore: c,
|
||||
Applier: winlayers.NewFileSystemApplierWithWindows(c, apply.NewFileSystemApplier(c)),
|
||||
Differ: winlayers.NewWalkingDiffWithWindows(c, walking.NewWalkingDiff(c)),
|
||||
ImageStore: nil, // explicitly
|
||||
Platforms: []specs.Platform{platforms.Normalize(platforms.DefaultSpec())},
|
||||
ID: id,
|
||||
Labels: xlabels,
|
||||
MetadataStore: md,
|
||||
Executor: exe,
|
||||
Snapshotter: containerdsnapshot.NewSnapshotter(mdb.Snapshotter(snFactory.Name), c, md, "buildkit", gc, idmap),
|
||||
ContentStore: c,
|
||||
Applier: winlayers.NewFileSystemApplierWithWindows(c, apply.NewFileSystemApplier(c)),
|
||||
Differ: winlayers.NewWalkingDiffWithWindows(c, walking.NewWalkingDiff(c)),
|
||||
ImageStore: nil, // explicitly
|
||||
Platforms: []specs.Platform{platforms.Normalize(platforms.DefaultSpec())},
|
||||
IdentityMapping: idmap,
|
||||
}
|
||||
return opt, nil
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ func newWorkerOpt(t *testing.T, processMode oci.ProcessMode) (base.WorkerOpt, fu
|
|||
},
|
||||
}
|
||||
rootless := false
|
||||
workerOpt, err := NewWorkerOpt(tmpdir, snFactory, rootless, processMode, nil)
|
||||
workerOpt, err := NewWorkerOpt(tmpdir, snFactory, rootless, processMode, nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
return workerOpt, cleanup
|
||||
|
|
Loading…
Reference in New Issue