Merge pull request #41601 from tiborvass/bk_vendor
vendor buildkit 6861f17f15364de0fe1fd1e6e8da07598a485123
This commit is contained in:
commit
cf0ce96eb1
271 changed files with 14580 additions and 3075 deletions
|
@ -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"
|
||||||
|
@ -31,6 +30,7 @@ import (
|
||||||
"github.com/moby/buildkit/cache"
|
"github.com/moby/buildkit/cache"
|
||||||
"github.com/moby/buildkit/client/llb"
|
"github.com/moby/buildkit/client/llb"
|
||||||
"github.com/moby/buildkit/session"
|
"github.com/moby/buildkit/session"
|
||||||
|
"github.com/moby/buildkit/solver"
|
||||||
"github.com/moby/buildkit/source"
|
"github.com/moby/buildkit/source"
|
||||||
"github.com/moby/buildkit/util/flightcontrol"
|
"github.com/moby/buildkit/util/flightcontrol"
|
||||||
"github.com/moby/buildkit/util/imageutil"
|
"github.com/moby/buildkit/util/imageutil"
|
||||||
|
@ -60,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: newResolverCache(),
|
|
||||||
}
|
|
||||||
|
|
||||||
return is, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID returns image scheme identifier
|
// ID returns image scheme identifier
|
||||||
|
@ -78,16 +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
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
||||||
|
@ -109,8 +93,15 @@ func (is *Source) resolveRemote(ctx context.Context, ref string, platform *ocisp
|
||||||
dgst digest.Digest
|
dgst digest.Digest
|
||||||
dt []byte
|
dt []byte
|
||||||
}
|
}
|
||||||
res, err := is.g.Do(ctx, ref, func(ctx context.Context) (interface{}, error) {
|
p := platforms.DefaultSpec()
|
||||||
dgst, dt, err := imageutil.Config(ctx, ref, is.getResolver(is.RegistryHosts, ref, sm, g), is.ContentStore, nil, platform)
|
if platform != nil {
|
||||||
|
p = *platform
|
||||||
|
}
|
||||||
|
// key is used to synchronize resolutions that can happen in parallel when doing multi-stage.
|
||||||
|
key := "getconfig::" + ref + "::" + platforms.Format(p)
|
||||||
|
res, err := is.g.Do(ctx, key, func(ctx context.Context) (interface{}, error) {
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
@ -168,7 +159,7 @@ func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt llb.Re
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve returns access to pulling for an identifier
|
// Resolve returns access to pulling for an identifier
|
||||||
func (is *Source) Resolve(ctx context.Context, id source.Identifier, sm *session.Manager) (source.SourceInstance, error) {
|
func (is *Source) Resolve(ctx context.Context, id source.Identifier, sm *session.Manager, vtx solver.Vertex) (source.SourceInstance, error) {
|
||||||
imageIdentifier, ok := id.(*source.ImageIdentifier)
|
imageIdentifier, ok := id.(*source.ImageIdentifier)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.Errorf("invalid image identifier %v", id)
|
return nil, errors.Errorf("invalid image identifier %v", id)
|
||||||
|
@ -191,29 +182,20 @@ func (is *Source) Resolve(ctx context.Context, id source.Identifier, sm *session
|
||||||
|
|
||||||
type puller struct {
|
type puller struct {
|
||||||
is *Source
|
is *Source
|
||||||
resolveOnce sync.Once
|
|
||||||
resolveLocalOnce sync.Once
|
resolveLocalOnce sync.Once
|
||||||
src *source.ImageIdentifier
|
src *source.ImageIdentifier
|
||||||
desc ocispec.Descriptor
|
desc ocispec.Descriptor
|
||||||
ref string
|
ref string
|
||||||
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(platform ocispec.Platform) (digest.Digest, error) {
|
||||||
dt, err := json.Marshal(struct {
|
dt, err := json.Marshal(struct {
|
||||||
Digest digest.Digest
|
Digest digest.Digest
|
||||||
OS string
|
OS string
|
||||||
|
@ -271,22 +253,23 @@ func (p *puller) resolveLocal() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *puller) resolve(ctx context.Context, g session.Group) error {
|
func (p *puller) resolve(ctx context.Context, g session.Group) error {
|
||||||
p.resolveOnce.Do(func() {
|
// key is used to synchronize resolutions that can happen in parallel when doing multi-stage.
|
||||||
|
key := "resolve::" + p.ref + "::" + platforms.Format(p.platform)
|
||||||
|
_, err := p.is.g.Do(ctx, key, func(ctx context.Context) (_ interface{}, err error) {
|
||||||
resolveProgressDone := oneOffProgress(ctx, "resolve "+p.src.Reference.String())
|
resolveProgressDone := oneOffProgress(ctx, "resolve "+p.src.Reference.String())
|
||||||
|
defer func() {
|
||||||
|
resolveProgressDone(err)
|
||||||
|
}()
|
||||||
|
|
||||||
ref, err := distreference.ParseNormalizedNamed(p.src.Reference.String())
|
ref, err := distreference.ParseNormalizedNamed(p.src.Reference.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.resolveErr = err
|
return nil, err
|
||||||
_ = resolveProgressDone(err)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.desc.Digest == "" && p.config == nil {
|
if p.desc.Digest == "" && p.config == nil {
|
||||||
origRef, desc, err := p.resolver(g).Resolve(ctx, ref.String())
|
origRef, desc, err := p.resolver(g).Resolve(ctx, ref.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.resolveErr = err
|
return nil, err
|
||||||
_ = resolveProgressDone(err)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p.desc = desc
|
p.desc = desc
|
||||||
|
@ -301,65 +284,61 @@ func (p *puller) resolve(ctx context.Context, g session.Group) error {
|
||||||
if p.config == nil && p.desc.MediaType != images.MediaTypeDockerSchema1Manifest {
|
if p.config == nil && p.desc.MediaType != images.MediaTypeDockerSchema1Manifest {
|
||||||
ref, err := distreference.WithDigest(ref, p.desc.Digest)
|
ref, err := distreference.WithDigest(ref, p.desc.Digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.resolveErr = err
|
return nil, err
|
||||||
_ = resolveProgressDone(err)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
_, dt, err := p.is.ResolveImageConfig(ctx, ref.String(), llb.ResolveImageConfigOpt{Platform: &p.platform, ResolveMode: resolveModeToString(p.src.ResolveMode)}, p.sm, g)
|
_, dt, err := p.is.ResolveImageConfig(ctx, ref.String(), llb.ResolveImageConfigOpt{Platform: &p.platform, ResolveMode: resolveModeToString(p.src.ResolveMode)}, p.sm, g)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.resolveErr = err
|
return nil, err
|
||||||
_ = resolveProgressDone(err)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p.config = dt
|
p.config = dt
|
||||||
}
|
}
|
||||||
_ = resolveProgressDone(nil)
|
return nil, nil
|
||||||
})
|
})
|
||||||
return p.resolveErr
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *puller) CacheKey(ctx context.Context, g session.Group, index int) (string, bool, error) {
|
func (p *puller) CacheKey(ctx context.Context, g session.Group, index int) (string, solver.CacheOpts, bool, error) {
|
||||||
p.resolveLocal()
|
p.resolveLocal()
|
||||||
|
|
||||||
if p.desc.Digest != "" && index == 0 {
|
if p.desc.Digest != "" && index == 0 {
|
||||||
dgst, err := p.mainManifestKey(p.desc.Digest, p.platform)
|
dgst, err := p.mainManifestKey(p.platform)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", false, err
|
return "", nil, false, err
|
||||||
}
|
}
|
||||||
return dgst.String(), false, nil
|
return dgst.String(), nil, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.config != nil {
|
if p.config != nil {
|
||||||
k := cacheKeyFromConfig(p.config).String()
|
k := cacheKeyFromConfig(p.config).String()
|
||||||
if k == "" {
|
if k == "" {
|
||||||
return digest.FromBytes(p.config).String(), true, nil
|
return digest.FromBytes(p.config).String(), nil, true, nil
|
||||||
}
|
}
|
||||||
return k, true, nil
|
return k, nil, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := p.resolve(ctx, g); err != nil {
|
if err := p.resolve(ctx, g); err != nil {
|
||||||
return "", false, err
|
return "", nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.desc.Digest != "" && index == 0 {
|
if p.desc.Digest != "" && index == 0 {
|
||||||
dgst, err := p.mainManifestKey(p.desc.Digest, p.platform)
|
dgst, err := p.mainManifestKey(p.platform)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", false, err
|
return "", nil, false, err
|
||||||
}
|
}
|
||||||
return dgst.String(), false, nil
|
return dgst.String(), nil, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
k := cacheKeyFromConfig(p.config).String()
|
k := cacheKeyFromConfig(p.config).String()
|
||||||
if k == "" {
|
if k == "" {
|
||||||
dgst, err := p.mainManifestKey(p.desc.Digest, p.platform)
|
dgst, err := p.mainManifestKey(p.platform)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", false, err
|
return "", nil, false, err
|
||||||
}
|
}
|
||||||
return dgst.String(), true, nil
|
return dgst.String(), nil, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return k, true, nil
|
return k, nil, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *puller) getRef(ctx context.Context, diffIDs []layer.DiffID, opts ...cache.RefOption) (cache.ImmutableRef, error) {
|
func (p *puller) getRef(ctx context.Context, diffIDs []layer.DiffID, opts ...cache.RefOption) (cache.ImmutableRef, error) {
|
||||||
|
@ -426,10 +405,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
|
||||||
|
@ -845,97 +820,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 *resolver.SessionAuthenticator
|
|
||||||
}
|
|
||||||
|
|
||||||
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 *resolver.SessionAuthenticator, 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 {
|
|
||||||
cr.auth.AddSession(g)
|
|
||||||
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 {
|
|
||||||
cr.auth.AddSession(g)
|
|
||||||
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
|
||||||
|
|
|
@ -34,7 +34,7 @@ import (
|
||||||
"github.com/moby/buildkit/frontend/gateway/forwarder"
|
"github.com/moby/buildkit/frontend/gateway/forwarder"
|
||||||
containerdsnapshot "github.com/moby/buildkit/snapshot/containerd"
|
containerdsnapshot "github.com/moby/buildkit/snapshot/containerd"
|
||||||
"github.com/moby/buildkit/solver/bboltcachestorage"
|
"github.com/moby/buildkit/solver/bboltcachestorage"
|
||||||
"github.com/moby/buildkit/util/binfmt_misc"
|
"github.com/moby/buildkit/util/archutil"
|
||||||
"github.com/moby/buildkit/util/entitlements"
|
"github.com/moby/buildkit/util/entitlements"
|
||||||
"github.com/moby/buildkit/util/leaseutil"
|
"github.com/moby/buildkit/util/leaseutil"
|
||||||
"github.com/moby/buildkit/worker"
|
"github.com/moby/buildkit/worker"
|
||||||
|
@ -166,7 +166,7 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
|
||||||
return nil, errors.Errorf("snapshotter doesn't support differ")
|
return nil, errors.Errorf("snapshotter doesn't support differ")
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := parsePlatforms(binfmt_misc.SupportedPlatforms(true))
|
p, err := parsePlatforms(archutil.SupportedPlatforms(true))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,11 +95,11 @@ func (iface *lnInterface) init(c libnetwork.NetworkController, n libnetwork.Netw
|
||||||
iface.ep = ep
|
iface.ep = ep
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iface *lnInterface) Set(s *specs.Spec) {
|
func (iface *lnInterface) Set(s *specs.Spec) error {
|
||||||
<-iface.ready
|
<-iface.ready
|
||||||
if iface.err != nil {
|
if iface.err != nil {
|
||||||
logrus.WithError(iface.err).Error("failed to set networking spec")
|
logrus.WithError(iface.err).Error("failed to set networking spec")
|
||||||
return
|
return iface.err
|
||||||
}
|
}
|
||||||
shortNetCtlrID := stringid.TruncateID(iface.provider.NetworkController.ID())
|
shortNetCtlrID := stringid.TruncateID(iface.provider.NetworkController.ID())
|
||||||
// attach netns to bridge within the container namespace, using reexec in a prestart hook
|
// attach netns to bridge within the container namespace, using reexec in a prestart hook
|
||||||
|
@ -109,6 +109,7 @@ func (iface *lnInterface) Set(s *specs.Spec) {
|
||||||
Args: []string{"libnetwork-setkey", "-exec-root=" + iface.provider.Config().Daemon.ExecRoot, iface.sbx.ContainerID(), shortNetCtlrID},
|
Args: []string{"libnetwork-setkey", "-exec-root=" + iface.provider.Config().Daemon.ExecRoot, iface.sbx.ContainerID(), shortNetCtlrID},
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iface *lnInterface) Close() error {
|
func (iface *lnInterface) Close() error {
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"github.com/docker/docker/daemon/config"
|
"github.com/docker/docker/daemon/config"
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
"github.com/docker/libnetwork"
|
"github.com/docker/libnetwork"
|
||||||
"github.com/moby/buildkit/cache"
|
|
||||||
"github.com/moby/buildkit/executor"
|
"github.com/moby/buildkit/executor"
|
||||||
"github.com/moby/buildkit/executor/oci"
|
"github.com/moby/buildkit/executor/oci"
|
||||||
)
|
)
|
||||||
|
@ -19,7 +18,7 @@ func newExecutor(_, _ string, _ libnetwork.NetworkController, _ *oci.DNSConfig,
|
||||||
type winExecutor struct {
|
type winExecutor struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *winExecutor) Run(ctx context.Context, id string, root cache.Mountable, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (err error) {
|
func (w *winExecutor) Run(ctx context.Context, id string, root executor.Mount, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (err error) {
|
||||||
return errors.New("buildkit executor not implemented for windows")
|
return errors.New("buildkit executor not implemented for windows")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ func emptyImageConfig() ([]byte, error) {
|
||||||
}
|
}
|
||||||
img.RootFS.Type = "layers"
|
img.RootFS.Type = "layers"
|
||||||
img.Config.WorkingDir = "/"
|
img.Config.WorkingDir = "/"
|
||||||
img.Config.Env = []string{"PATH=" + system.DefaultPathEnv}
|
img.Config.Env = []string{"PATH=" + system.DefaultPathEnvUnix}
|
||||||
dt, err := json.Marshal(img)
|
dt, err := json.Marshal(img)
|
||||||
return dt, errors.Wrap(err, "failed to create empty image config")
|
return dt, errors.Wrap(err, "failed to create empty image config")
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,13 +33,15 @@ import (
|
||||||
"github.com/moby/buildkit/session"
|
"github.com/moby/buildkit/session"
|
||||||
"github.com/moby/buildkit/snapshot"
|
"github.com/moby/buildkit/snapshot"
|
||||||
"github.com/moby/buildkit/solver"
|
"github.com/moby/buildkit/solver"
|
||||||
|
"github.com/moby/buildkit/solver/llbsolver/mounts"
|
||||||
"github.com/moby/buildkit/solver/llbsolver/ops"
|
"github.com/moby/buildkit/solver/llbsolver/ops"
|
||||||
"github.com/moby/buildkit/solver/pb"
|
"github.com/moby/buildkit/solver/pb"
|
||||||
"github.com/moby/buildkit/source"
|
"github.com/moby/buildkit/source"
|
||||||
"github.com/moby/buildkit/source/git"
|
"github.com/moby/buildkit/source/git"
|
||||||
"github.com/moby/buildkit/source/http"
|
"github.com/moby/buildkit/source/http"
|
||||||
"github.com/moby/buildkit/source/local"
|
"github.com/moby/buildkit/source/local"
|
||||||
"github.com/moby/buildkit/util/binfmt_misc"
|
"github.com/moby/buildkit/util/archutil"
|
||||||
|
"github.com/moby/buildkit/util/compression"
|
||||||
"github.com/moby/buildkit/util/contentutil"
|
"github.com/moby/buildkit/util/contentutil"
|
||||||
"github.com/moby/buildkit/util/progress"
|
"github.com/moby/buildkit/util/progress"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
|
@ -147,7 +149,7 @@ func (w *Worker) Platforms(noCache bool) []ocispec.Platform {
|
||||||
for _, p := range w.Opt.Platforms {
|
for _, p := range w.Opt.Platforms {
|
||||||
pm[platforms.Format(p)] = struct{}{}
|
pm[platforms.Format(p)] = struct{}{}
|
||||||
}
|
}
|
||||||
for _, p := range binfmt_misc.SupportedPlatforms(noCache) {
|
for _, p := range archutil.SupportedPlatforms(noCache) {
|
||||||
if _, ok := pm[p]; !ok {
|
if _, ok := pm[p]; !ok {
|
||||||
pp, _ := platforms.Parse(p)
|
pp, _ := platforms.Parse(p)
|
||||||
w.Opt.Platforms = append(w.Opt.Platforms, pp)
|
w.Opt.Platforms = append(w.Opt.Platforms, pp)
|
||||||
|
@ -170,13 +172,18 @@ func (w *Worker) ContentStore() content.Store {
|
||||||
return w.Opt.ContentStore
|
return w.Opt.ContentStore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MetadataStore returns the metadata store
|
||||||
|
func (w *Worker) MetadataStore() *metadata.Store {
|
||||||
|
return w.Opt.MetadataStore
|
||||||
|
}
|
||||||
|
|
||||||
// LoadRef loads a reference by ID
|
// LoadRef loads a reference by ID
|
||||||
func (w *Worker) LoadRef(id string, hidden bool) (cache.ImmutableRef, error) {
|
func (w *Worker) LoadRef(ctx context.Context, id string, hidden bool) (cache.ImmutableRef, error) {
|
||||||
var opts []cache.RefOption
|
var opts []cache.RefOption
|
||||||
if hidden {
|
if hidden {
|
||||||
opts = append(opts, cache.NoUpdateLastUsed)
|
opts = append(opts, cache.NoUpdateLastUsed)
|
||||||
}
|
}
|
||||||
return w.CacheManager().Get(context.TODO(), id, opts...)
|
return w.CacheManager().Get(ctx, id, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResolveOp converts a LLB vertex into a LLB operation
|
// ResolveOp converts a LLB vertex into a LLB operation
|
||||||
|
@ -186,9 +193,9 @@ func (w *Worker) ResolveOp(v solver.Vertex, s frontend.FrontendLLBBridge, sm *se
|
||||||
case *pb.Op_Source:
|
case *pb.Op_Source:
|
||||||
return ops.NewSourceOp(v, op, baseOp.Platform, w.SourceManager, sm, w)
|
return ops.NewSourceOp(v, op, baseOp.Platform, w.SourceManager, sm, w)
|
||||||
case *pb.Op_Exec:
|
case *pb.Op_Exec:
|
||||||
return ops.NewExecOp(v, op, baseOp.Platform, w.CacheManager(), sm, w.MetadataStore, w.Executor(), w)
|
return ops.NewExecOp(v, op, baseOp.Platform, w.CacheManager(), sm, w.Opt.MetadataStore, w.Executor(), w)
|
||||||
case *pb.Op_File:
|
case *pb.Op_File:
|
||||||
return ops.NewFileOp(v, op, w.CacheManager(), w.MetadataStore, w)
|
return ops.NewFileOp(v, op, w.CacheManager(), w.Opt.MetadataStore, w)
|
||||||
case *pb.Op_Build:
|
case *pb.Op_Build:
|
||||||
return ops.NewBuildOp(v, op, s, w)
|
return ops.NewBuildOp(v, op, s, w)
|
||||||
}
|
}
|
||||||
|
@ -230,7 +237,7 @@ func (w *Worker) Exporter(name string, sm *session.Manager) (exporter.Exporter,
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRemote returns a remote snapshot reference for a local one
|
// GetRemote returns a remote snapshot reference for a local one
|
||||||
func (w *Worker) GetRemote(ctx context.Context, ref cache.ImmutableRef, createIfNeeded bool) (*solver.Remote, error) {
|
func (w *Worker) GetRemote(ctx context.Context, ref cache.ImmutableRef, createIfNeeded bool, _ compression.Type, _ session.Group) (*solver.Remote, error) {
|
||||||
var diffIDs []layer.DiffID
|
var diffIDs []layer.DiffID
|
||||||
var err error
|
var err error
|
||||||
if !createIfNeeded {
|
if !createIfNeeded {
|
||||||
|
@ -265,13 +272,13 @@ func (w *Worker) GetRemote(ctx context.Context, ref cache.ImmutableRef, createIf
|
||||||
|
|
||||||
// PruneCacheMounts removes the current cache snapshots for specified IDs
|
// PruneCacheMounts removes the current cache snapshots for specified IDs
|
||||||
func (w *Worker) PruneCacheMounts(ctx context.Context, ids []string) error {
|
func (w *Worker) PruneCacheMounts(ctx context.Context, ids []string) error {
|
||||||
mu := ops.CacheMountsLocker()
|
mu := mounts.CacheMountsLocker()
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
|
|
||||||
for _, id := range ids {
|
for _, id := range ids {
|
||||||
id = "cache-dir:" + id
|
id = "cache-dir:" + id
|
||||||
sis, err := w.MetadataStore.Search(id)
|
sis, err := w.Opt.MetadataStore.Search(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -300,7 +307,7 @@ func (w *Worker) PruneCacheMounts(ctx context.Context, ids []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ops.ClearActiveCacheMounts()
|
mounts.ClearActiveCacheMounts()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -235,8 +235,10 @@ func processMetaArg(meta instructions.ArgCommand, shlex *shell.Lex, args *BuildA
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
args.AddArg(meta.Key, meta.Value)
|
for _, arg := range meta.Args {
|
||||||
args.AddMetaArg(meta.Key, meta.Value)
|
args.AddArg(arg.Key, arg.Value)
|
||||||
|
args.AddMetaArg(arg.Key, arg.Value)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -587,14 +587,21 @@ func dispatchStopSignal(d dispatchRequest, c *instructions.StopSignalCommand) er
|
||||||
// to builder using the --build-arg flag for expansion/substitution or passing to 'run'.
|
// to builder using the --build-arg flag for expansion/substitution or passing to 'run'.
|
||||||
// Dockerfile author may optionally set a default value of this variable.
|
// Dockerfile author may optionally set a default value of this variable.
|
||||||
func dispatchArg(d dispatchRequest, c *instructions.ArgCommand) error {
|
func dispatchArg(d dispatchRequest, c *instructions.ArgCommand) error {
|
||||||
|
var commitStr strings.Builder
|
||||||
commitStr := "ARG " + c.Key
|
commitStr.WriteString("ARG ")
|
||||||
if c.Value != nil {
|
for i, arg := range c.Args {
|
||||||
commitStr += "=" + *c.Value
|
if i > 0 {
|
||||||
|
commitStr.WriteString(" ")
|
||||||
|
}
|
||||||
|
commitStr.WriteString(arg.Key)
|
||||||
|
if arg.Value != nil {
|
||||||
|
commitStr.WriteString("=")
|
||||||
|
commitStr.WriteString(*arg.Value)
|
||||||
|
}
|
||||||
|
d.state.buildArgs.AddArg(arg.Key, arg.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.state.buildArgs.AddArg(c.Key, c.Value)
|
return d.builder.commit(d.state, commitStr.String())
|
||||||
return d.builder.commit(d.state, commitStr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SHELL powershell -command
|
// SHELL powershell -command
|
||||||
|
|
|
@ -139,10 +139,10 @@ func TestFromWithArg(t *testing.T) {
|
||||||
args := NewBuildArgs(make(map[string]*string))
|
args := NewBuildArgs(make(map[string]*string))
|
||||||
|
|
||||||
val := "sometag"
|
val := "sometag"
|
||||||
metaArg := instructions.ArgCommand{KeyValuePairOptional: instructions.KeyValuePairOptional{
|
metaArg := instructions.ArgCommand{Args: []instructions.KeyValuePairOptional{{
|
||||||
Key: "THETAG",
|
Key: "THETAG",
|
||||||
Value: &val,
|
Value: &val,
|
||||||
}}
|
}}}
|
||||||
cmd := &instructions.Stage{
|
cmd := &instructions.Stage{
|
||||||
BaseName: "alpine:${THETAG}",
|
BaseName: "alpine:${THETAG}",
|
||||||
}
|
}
|
||||||
|
@ -395,7 +395,7 @@ func TestArg(t *testing.T) {
|
||||||
|
|
||||||
argName := "foo"
|
argName := "foo"
|
||||||
argVal := "bar"
|
argVal := "bar"
|
||||||
cmd := &instructions.ArgCommand{KeyValuePairOptional: instructions.KeyValuePairOptional{Key: argName, Value: &argVal}}
|
cmd := &instructions.ArgCommand{Args: []instructions.KeyValuePairOptional{{Key: argName, Value: &argVal}}}
|
||||||
err := dispatch(sb, cmd)
|
err := dispatch(sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
|
17
builder/dockerignore/deprecated.go
Normal file
17
builder/dockerignore/deprecated.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Package dockerignore is deprecated. Use github.com/moby/buildkit/frontend/dockerfile/dockerignore instead.
|
||||||
|
package dockerignore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/moby/buildkit/frontend/dockerfile/dockerignore"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReadAll reads a .dockerignore file and returns the list of file patterns
|
||||||
|
// to ignore. Note this will trim whitespace from each line as well
|
||||||
|
// as use GO's "clean" func to get the shortest/cleanest path for each.
|
||||||
|
//
|
||||||
|
// Deprecated: use github.com/moby/buildkit/frontend/dockerfile/dockerignore.ReadAll instead.
|
||||||
|
func ReadAll(reader io.Reader) ([]string, error) {
|
||||||
|
return dockerignore.ReadAll(reader)
|
||||||
|
}
|
|
@ -1,69 +0,0 @@
|
||||||
package dockerignore // import "github.com/docker/docker/builder/dockerignore"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestReadAll(t *testing.T) {
|
|
||||||
tmpDir, err := ioutil.TempDir("", "dockerignore-test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(tmpDir)
|
|
||||||
|
|
||||||
di, err := ReadAll(nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Expected not to have error, got %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if diLen := len(di); diLen != 0 {
|
|
||||||
t.Fatalf("Expected to have zero dockerignore entry, got %d", diLen)
|
|
||||||
}
|
|
||||||
|
|
||||||
diName := filepath.Join(tmpDir, ".dockerignore")
|
|
||||||
content := fmt.Sprintf("test1\n/test2\n/a/file/here\n\nlastfile\n# this is a comment\n! /inverted/abs/path\n!\n! \n")
|
|
||||||
err = ioutil.WriteFile(diName, []byte(content), 0777)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
diFd, err := os.Open(diName)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer diFd.Close()
|
|
||||||
|
|
||||||
di, err = ReadAll(diFd)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(di) != 7 {
|
|
||||||
t.Fatalf("Expected 7 entries, got %v", len(di))
|
|
||||||
}
|
|
||||||
if di[0] != "test1" {
|
|
||||||
t.Fatal("First element is not test1")
|
|
||||||
}
|
|
||||||
if di[1] != "test2" { // according to https://docs.docker.com/engine/reference/builder/#dockerignore-file, /foo/bar should be treated as foo/bar
|
|
||||||
t.Fatal("Second element is not test2")
|
|
||||||
}
|
|
||||||
if di[2] != "a/file/here" { // according to https://docs.docker.com/engine/reference/builder/#dockerignore-file, /foo/bar should be treated as foo/bar
|
|
||||||
t.Fatal("Third element is not a/file/here")
|
|
||||||
}
|
|
||||||
if di[3] != "lastfile" {
|
|
||||||
t.Fatal("Fourth element is not lastfile")
|
|
||||||
}
|
|
||||||
if di[4] != "!inverted/abs/path" {
|
|
||||||
t.Fatal("Fifth element is not !inverted/abs/path")
|
|
||||||
}
|
|
||||||
if di[5] != "!" {
|
|
||||||
t.Fatalf("Sixth element is not !, but %s", di[5])
|
|
||||||
}
|
|
||||||
if di[6] != "!" {
|
|
||||||
t.Fatalf("Seventh element is not !, but %s", di[6])
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,10 +11,10 @@ import (
|
||||||
"github.com/containerd/continuity/driver"
|
"github.com/containerd/continuity/driver"
|
||||||
"github.com/docker/docker/api/types/backend"
|
"github.com/docker/docker/api/types/backend"
|
||||||
"github.com/docker/docker/builder"
|
"github.com/docker/docker/builder"
|
||||||
"github.com/docker/docker/builder/dockerignore"
|
|
||||||
"github.com/docker/docker/errdefs"
|
"github.com/docker/docker/errdefs"
|
||||||
"github.com/docker/docker/pkg/fileutils"
|
"github.com/docker/docker/pkg/fileutils"
|
||||||
"github.com/docker/docker/pkg/urlutil"
|
"github.com/docker/docker/pkg/urlutil"
|
||||||
|
"github.com/moby/buildkit/frontend/dockerfile/dockerignore"
|
||||||
"github.com/moby/buildkit/frontend/dockerfile/parser"
|
"github.com/moby/buildkit/frontend/dockerfile/parser"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
|
@ -5608,30 +5608,6 @@ func (s *DockerSuite) TestBuildWithExtraHostInvalidFormat(c *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DockerSuite) TestBuildContChar(c *testing.T) {
|
|
||||||
name := "testbuildcontchar"
|
|
||||||
|
|
||||||
buildImage(name, build.WithDockerfile(`FROM busybox\`)).Assert(c, icmd.Expected{
|
|
||||||
Out: "Step 1/1 : FROM busybox",
|
|
||||||
})
|
|
||||||
|
|
||||||
result := buildImage(name, build.WithDockerfile(`FROM busybox
|
|
||||||
RUN echo hi \`))
|
|
||||||
result.Assert(c, icmd.Success)
|
|
||||||
assert.Assert(c, strings.Contains(result.Combined(), "Step 1/2 : FROM busybox"))
|
|
||||||
assert.Assert(c, strings.Contains(result.Combined(), "Step 2/2 : RUN echo hi\n"))
|
|
||||||
result = buildImage(name, build.WithDockerfile(`FROM busybox
|
|
||||||
RUN echo hi \\`))
|
|
||||||
result.Assert(c, icmd.Success)
|
|
||||||
assert.Assert(c, strings.Contains(result.Combined(), "Step 1/2 : FROM busybox"))
|
|
||||||
assert.Assert(c, strings.Contains(result.Combined(), "Step 2/2 : RUN echo hi \\\n"))
|
|
||||||
result = buildImage(name, build.WithDockerfile(`FROM busybox
|
|
||||||
RUN echo hi \\\`))
|
|
||||||
result.Assert(c, icmd.Success)
|
|
||||||
assert.Assert(c, strings.Contains(result.Combined(), "Step 1/2 : FROM busybox"))
|
|
||||||
assert.Assert(c, strings.Contains(result.Combined(), "Step 2/2 : RUN echo hi \\\\\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *DockerSuite) TestBuildMultiStageCopyFromSyntax(c *testing.T) {
|
func (s *DockerSuite) TestBuildMultiStageCopyFromSyntax(c *testing.T) {
|
||||||
dockerfile := `
|
dockerfile := `
|
||||||
FROM busybox AS first
|
FROM busybox AS first
|
||||||
|
|
15
vendor.conf
15
vendor.conf
|
@ -33,13 +33,14 @@ github.com/imdario/mergo 1afb36080aec31e0d1528973ebe6
|
||||||
golang.org/x/sync cd5d95a43a6e21273425c7ae415d3df9ea832eeb
|
golang.org/x/sync cd5d95a43a6e21273425c7ae415d3df9ea832eeb
|
||||||
|
|
||||||
# buildkit
|
# buildkit
|
||||||
github.com/moby/buildkit 4d1f260e8490ec438ab66e08bb105577aca0ce06
|
github.com/moby/buildkit 6861f17f15364de0fe1fd1e6e8da07598a485123
|
||||||
github.com/tonistiigi/fsutil ae3a8d753069d0f76fbee396457e8b6cfd7cb8c3
|
github.com/tonistiigi/fsutil c3ed55f3b48161fd3dc42c17ba09e12ac52d57dc
|
||||||
|
github.com/tonistiigi/units 6950e57a87eaf136bbe44ef2ec8e75b9e3569de2
|
||||||
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
|
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
|
||||||
github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7
|
github.com/opentracing/opentracing-go d34af3eaa63c4d08ab54863a4bdd0daa45212e12 # v1.2.0
|
||||||
github.com/google/shlex e7afc7fbc51079733e9468cdfd1efcd7d196cd1d
|
github.com/google/shlex e7afc7fbc51079733e9468cdfd1efcd7d196cd1d
|
||||||
github.com/opentracing-contrib/go-stdlib b1a47cfbdd7543e70e9ef3e73d0802ad306cc1cc
|
github.com/opentracing-contrib/go-stdlib 8a6ff1ad1691a29e4f7b5d46604f97634997c8c4 # v1.0.0
|
||||||
github.com/mitchellh/hashstructure 2bca23e0e452137f789efbc8610126fd8b94f73b
|
github.com/mitchellh/hashstructure a38c50148365edc8df43c1580c48fb2b3a1e9cd7 # v1.0.0
|
||||||
github.com/gofrs/flock 6caa7350c26b838538005fae7dbee4e69d9398db # v0.7.3
|
github.com/gofrs/flock 6caa7350c26b838538005fae7dbee4e69d9398db # v0.7.3
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware 3c51f7f332123e8be5a157c0802a228ac85bf9db # v1.2.0
|
github.com/grpc-ecosystem/go-grpc-middleware 3c51f7f332123e8be5a157c0802a228ac85bf9db # v1.2.0
|
||||||
|
|
||||||
|
@ -129,12 +130,12 @@ github.com/googleapis/gax-go bd5b16380fd03dc758d11cef74ba
|
||||||
google.golang.org/genproto 3f1135a288c9a07e340ae8ba4cc6c7065a3160e8
|
google.golang.org/genproto 3f1135a288c9a07e340ae8ba4cc6c7065a3160e8
|
||||||
|
|
||||||
# containerd
|
# containerd
|
||||||
github.com/containerd/containerd c623d1b36f09f8ef6536a057bd658b3aa8632828 # v1.4.1
|
github.com/containerd/containerd d4e78200d6da62480c85bf6f26b7221ea938f396
|
||||||
github.com/containerd/fifo f15a3290365b9d2627d189e619ab4008e0069caf
|
github.com/containerd/fifo f15a3290365b9d2627d189e619ab4008e0069caf
|
||||||
github.com/containerd/continuity efbc4488d8fe1bdc16bde3b2d2990d9b3a899165
|
github.com/containerd/continuity efbc4488d8fe1bdc16bde3b2d2990d9b3a899165
|
||||||
github.com/containerd/cgroups 318312a373405e5e91134d8063d04d59768a1bff
|
github.com/containerd/cgroups 318312a373405e5e91134d8063d04d59768a1bff
|
||||||
github.com/containerd/console 5d7e1412f07b502a01029ea20e20e0d2be31fa7c # v1.0.1
|
github.com/containerd/console 5d7e1412f07b502a01029ea20e20e0d2be31fa7c # v1.0.1
|
||||||
github.com/containerd/go-runc 7016d3ce2328dd2cb1192b2076ebd565c4e8df0c
|
github.com/containerd/go-runc 16b287bc67d069a60fa48db15f330b790b74365b
|
||||||
github.com/containerd/typeurl cd3ce7159eae562a4f60ceff37dada11a939d247 # v1.0.1
|
github.com/containerd/typeurl cd3ce7159eae562a4f60ceff37dada11a939d247 # v1.0.1
|
||||||
github.com/containerd/ttrpc 72bb1b21c5b0a4a107f59dd85f6ab58e564b68d6 # v1.0.1
|
github.com/containerd/ttrpc 72bb1b21c5b0a4a107f59dd85f6ab58e564b68d6 # v1.0.1
|
||||||
github.com/gogo/googleapis 01e0f9cca9b92166042241267ee2a5cdf5cff46c # v1.3.2
|
github.com/gogo/googleapis 01e0f9cca9b92166042241267ee2a5cdf5cff46c # v1.3.2
|
||||||
|
|
19
vendor/github.com/containerd/containerd/README.md
generated
vendored
19
vendor/github.com/containerd/containerd/README.md
generated
vendored
|
@ -10,10 +10,24 @@
|
||||||
|
|
||||||
containerd is an industry-standard container runtime with an emphasis on simplicity, robustness and portability. It is available as a daemon for Linux and Windows, which can manage the complete container lifecycle of its host system: image transfer and storage, container execution and supervision, low-level storage and network attachments, etc.
|
containerd is an industry-standard container runtime with an emphasis on simplicity, robustness and portability. It is available as a daemon for Linux and Windows, which can manage the complete container lifecycle of its host system: image transfer and storage, container execution and supervision, low-level storage and network attachments, etc.
|
||||||
|
|
||||||
|
containerd is a member of CNCF with ['graduated'](https://landscape.cncf.io/selected=containerd) status.
|
||||||
|
|
||||||
containerd is designed to be embedded into a larger system, rather than being used directly by developers or end-users.
|
containerd is designed to be embedded into a larger system, rather than being used directly by developers or end-users.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## Now Recruiting
|
||||||
|
|
||||||
|
We are a large inclusive OSS project that is welcoming help of any kind shape or form:
|
||||||
|
* Documentation help is needed to make the product easier to consume and extend.
|
||||||
|
* We need OSS community outreach / organizing help to get the word out; manage
|
||||||
|
and create messaging and educational content; and to help with social media, community forums/groups, and google groups.
|
||||||
|
* We are actively inviting new [security advisors](https://github.com/containerd/project/blob/master/GOVERNANCE.md#security-advisors) to join the team.
|
||||||
|
* New sub-projects are being created, core and non-core that could use additional development help.
|
||||||
|
* Each of the [containerd projects](https://github.com/containerd) has a list of issues currently being worked on or that need help resolving.
|
||||||
|
- If the issue has not already been assigned to someone, or has not made recent progress and you are interested, please inquire.
|
||||||
|
- If you are interested in starting with a smaller / beginner level issue, look for issues with an `exp/beginner` tag, for example [containerd/containerd beginner issues.](https://github.com/containerd/containerd/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%2Fbeginner)
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
See our documentation on [containerd.io](https://containerd.io):
|
See our documentation on [containerd.io](https://containerd.io):
|
||||||
|
@ -250,10 +264,7 @@ loaded for the user's shell environment.
|
||||||
For async communication and long running discussions please use issues and pull requests on the github repo.
|
For async communication and long running discussions please use issues and pull requests on the github repo.
|
||||||
This will be the best place to discuss design and implementation.
|
This will be the best place to discuss design and implementation.
|
||||||
|
|
||||||
For sync communication we have a community slack with a #containerd channel that everyone is welcome to join and chat about development.
|
For sync communication catch us in the `#containerd` and `#containerd-dev` slack channels on Cloud Native Computing Foundation's (CNCF) slack - `cloud-native.slack.com`. Everyone is welcome to join and chat. [Get Invite to CNCF slack.](https://slack.cncf.io)
|
||||||
|
|
||||||
**Slack:** Catch us in the #containerd and #containerd-dev channels on dockercommunity.slack.com.
|
|
||||||
[Click here for an invite to docker community slack.](https://dockr.ly/slack)
|
|
||||||
|
|
||||||
### Security audit
|
### Security audit
|
||||||
|
|
||||||
|
|
206
vendor/github.com/containerd/containerd/remotes/docker/auth/fetch.go
generated
vendored
Normal file
206
vendor/github.com/containerd/containerd/remotes/docker/auth/fetch.go
generated
vendored
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/log"
|
||||||
|
remoteserrors "github.com/containerd/containerd/remotes/errors"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/net/context/ctxhttp"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrNoToken is returned if a request is successful but the body does not
|
||||||
|
// contain an authorization token.
|
||||||
|
ErrNoToken = errors.New("authorization server did not include a token in the response")
|
||||||
|
)
|
||||||
|
|
||||||
|
// GenerateTokenOptions generates options for fetching a token based on a challenge
|
||||||
|
func GenerateTokenOptions(ctx context.Context, host, username, secret string, c Challenge) (TokenOptions, error) {
|
||||||
|
realm, ok := c.Parameters["realm"]
|
||||||
|
if !ok {
|
||||||
|
return TokenOptions{}, errors.New("no realm specified for token auth challenge")
|
||||||
|
}
|
||||||
|
|
||||||
|
realmURL, err := url.Parse(realm)
|
||||||
|
if err != nil {
|
||||||
|
return TokenOptions{}, errors.Wrap(err, "invalid token auth challenge realm")
|
||||||
|
}
|
||||||
|
|
||||||
|
to := TokenOptions{
|
||||||
|
Realm: realmURL.String(),
|
||||||
|
Service: c.Parameters["service"],
|
||||||
|
Username: username,
|
||||||
|
Secret: secret,
|
||||||
|
}
|
||||||
|
|
||||||
|
scope, ok := c.Parameters["scope"]
|
||||||
|
if ok {
|
||||||
|
to.Scopes = append(to.Scopes, scope)
|
||||||
|
} else {
|
||||||
|
log.G(ctx).WithField("host", host).Debug("no scope specified for token auth challenge")
|
||||||
|
}
|
||||||
|
|
||||||
|
return to, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TokenOptions are optios for requesting a token
|
||||||
|
type TokenOptions struct {
|
||||||
|
Realm string
|
||||||
|
Service string
|
||||||
|
Scopes []string
|
||||||
|
Username string
|
||||||
|
Secret string
|
||||||
|
}
|
||||||
|
|
||||||
|
// OAuthTokenResponse is response from fetching token with a OAuth POST request
|
||||||
|
type OAuthTokenResponse struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
ExpiresIn int `json:"expires_in"`
|
||||||
|
IssuedAt time.Time `json:"issued_at"`
|
||||||
|
Scope string `json:"scope"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchTokenWithOAuth fetches a token using a POST request
|
||||||
|
func FetchTokenWithOAuth(ctx context.Context, client *http.Client, headers http.Header, clientID string, to TokenOptions) (*OAuthTokenResponse, error) {
|
||||||
|
form := url.Values{}
|
||||||
|
if len(to.Scopes) > 0 {
|
||||||
|
form.Set("scope", strings.Join(to.Scopes, " "))
|
||||||
|
}
|
||||||
|
form.Set("service", to.Service)
|
||||||
|
form.Set("client_id", clientID)
|
||||||
|
|
||||||
|
if to.Username == "" {
|
||||||
|
form.Set("grant_type", "refresh_token")
|
||||||
|
form.Set("refresh_token", to.Secret)
|
||||||
|
} else {
|
||||||
|
form.Set("grant_type", "password")
|
||||||
|
form.Set("username", to.Username)
|
||||||
|
form.Set("password", to.Secret)
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", to.Realm, strings.NewReader(form.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
|
||||||
|
if headers != nil {
|
||||||
|
for k, v := range headers {
|
||||||
|
req.Header[k] = append(req.Header[k], v...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := ctxhttp.Do(ctx, client, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode < 200 || resp.StatusCode >= 400 {
|
||||||
|
return nil, errors.WithStack(remoteserrors.NewUnexpectedStatusErr(resp))
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(resp.Body)
|
||||||
|
|
||||||
|
var tr OAuthTokenResponse
|
||||||
|
if err = decoder.Decode(&tr); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "unable to decode token response")
|
||||||
|
}
|
||||||
|
|
||||||
|
if tr.AccessToken == "" {
|
||||||
|
return nil, errors.WithStack(ErrNoToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &tr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchTokenResponse is response from fetching token with GET request
|
||||||
|
type FetchTokenResponse struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
ExpiresIn int `json:"expires_in"`
|
||||||
|
IssuedAt time.Time `json:"issued_at"`
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchToken fetches a token using a GET request
|
||||||
|
func FetchToken(ctx context.Context, client *http.Client, headers http.Header, to TokenOptions) (*FetchTokenResponse, error) {
|
||||||
|
req, err := http.NewRequest("GET", to.Realm, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if headers != nil {
|
||||||
|
for k, v := range headers {
|
||||||
|
req.Header[k] = append(req.Header[k], v...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reqParams := req.URL.Query()
|
||||||
|
|
||||||
|
if to.Service != "" {
|
||||||
|
reqParams.Add("service", to.Service)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, scope := range to.Scopes {
|
||||||
|
reqParams.Add("scope", scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
if to.Secret != "" {
|
||||||
|
req.SetBasicAuth(to.Username, to.Secret)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.URL.RawQuery = reqParams.Encode()
|
||||||
|
|
||||||
|
resp, err := ctxhttp.Do(ctx, client, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode < 200 || resp.StatusCode >= 400 {
|
||||||
|
return nil, errors.WithStack(remoteserrors.NewUnexpectedStatusErr(resp))
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(resp.Body)
|
||||||
|
|
||||||
|
var tr FetchTokenResponse
|
||||||
|
if err = decoder.Decode(&tr); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "unable to decode token response")
|
||||||
|
}
|
||||||
|
|
||||||
|
// `access_token` is equivalent to `token` and if both are specified
|
||||||
|
// the choice is undefined. Canonicalize `access_token` by sticking
|
||||||
|
// things in `token`.
|
||||||
|
if tr.AccessToken != "" {
|
||||||
|
tr.Token = tr.AccessToken
|
||||||
|
}
|
||||||
|
|
||||||
|
if tr.Token == "" {
|
||||||
|
return nil, errors.WithStack(ErrNoToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &tr, nil
|
||||||
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package docker
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -22,31 +22,35 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type authenticationScheme byte
|
// AuthenticationScheme defines scheme of the authentication method
|
||||||
|
type AuthenticationScheme byte
|
||||||
|
|
||||||
const (
|
const (
|
||||||
basicAuth authenticationScheme = 1 << iota // Defined in RFC 7617
|
// BasicAuth is scheme for Basic HTTP Authentication RFC 7617
|
||||||
digestAuth // Defined in RFC 7616
|
BasicAuth AuthenticationScheme = 1 << iota
|
||||||
bearerAuth // Defined in RFC 6750
|
// DigestAuth is scheme for HTTP Digest Access Authentication RFC 7616
|
||||||
|
DigestAuth
|
||||||
|
// BearerAuth is scheme for OAuth 2.0 Bearer Tokens RFC 6750
|
||||||
|
BearerAuth
|
||||||
)
|
)
|
||||||
|
|
||||||
// challenge carries information from a WWW-Authenticate response header.
|
// Challenge carries information from a WWW-Authenticate response header.
|
||||||
// See RFC 2617.
|
// See RFC 2617.
|
||||||
type challenge struct {
|
type Challenge struct {
|
||||||
// scheme is the auth-scheme according to RFC 2617
|
// scheme is the auth-scheme according to RFC 2617
|
||||||
scheme authenticationScheme
|
Scheme AuthenticationScheme
|
||||||
|
|
||||||
// parameters are the auth-params according to RFC 2617
|
// parameters are the auth-params according to RFC 2617
|
||||||
parameters map[string]string
|
Parameters map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
type byScheme []challenge
|
type byScheme []Challenge
|
||||||
|
|
||||||
func (bs byScheme) Len() int { return len(bs) }
|
func (bs byScheme) Len() int { return len(bs) }
|
||||||
func (bs byScheme) Swap(i, j int) { bs[i], bs[j] = bs[j], bs[i] }
|
func (bs byScheme) Swap(i, j int) { bs[i], bs[j] = bs[j], bs[i] }
|
||||||
|
|
||||||
// Sort in priority order: token > digest > basic
|
// Sort in priority order: token > digest > basic
|
||||||
func (bs byScheme) Less(i, j int) bool { return bs[i].scheme > bs[j].scheme }
|
func (bs byScheme) Less(i, j int) bool { return bs[i].Scheme > bs[j].Scheme }
|
||||||
|
|
||||||
// Octet types from RFC 2616.
|
// Octet types from RFC 2616.
|
||||||
type octetType byte
|
type octetType byte
|
||||||
|
@ -90,22 +94,23 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseAuthHeader(header http.Header) []challenge {
|
// ParseAuthHeader parses challenges from WWW-Authenticate header
|
||||||
challenges := []challenge{}
|
func ParseAuthHeader(header http.Header) []Challenge {
|
||||||
|
challenges := []Challenge{}
|
||||||
for _, h := range header[http.CanonicalHeaderKey("WWW-Authenticate")] {
|
for _, h := range header[http.CanonicalHeaderKey("WWW-Authenticate")] {
|
||||||
v, p := parseValueAndParams(h)
|
v, p := parseValueAndParams(h)
|
||||||
var s authenticationScheme
|
var s AuthenticationScheme
|
||||||
switch v {
|
switch v {
|
||||||
case "basic":
|
case "basic":
|
||||||
s = basicAuth
|
s = BasicAuth
|
||||||
case "digest":
|
case "digest":
|
||||||
s = digestAuth
|
s = DigestAuth
|
||||||
case "bearer":
|
case "bearer":
|
||||||
s = bearerAuth
|
s = BearerAuth
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
challenges = append(challenges, challenge{scheme: s, parameters: p})
|
challenges = append(challenges, Challenge{Scheme: s, Parameters: p})
|
||||||
}
|
}
|
||||||
sort.Stable(byScheme(challenges))
|
sort.Stable(byScheme(challenges))
|
||||||
return challenges
|
return challenges
|
263
vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
generated
vendored
263
vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
generated
vendored
|
@ -19,21 +19,17 @@ package docker
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
|
"github.com/containerd/containerd/remotes/docker/auth"
|
||||||
|
remoteerrors "github.com/containerd/containerd/remotes/errors"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/net/context/ctxhttp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type dockerAuthorizer struct {
|
type dockerAuthorizer struct {
|
||||||
|
@ -135,8 +131,8 @@ func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.R
|
||||||
|
|
||||||
a.mu.Lock()
|
a.mu.Lock()
|
||||||
defer a.mu.Unlock()
|
defer a.mu.Unlock()
|
||||||
for _, c := range parseAuthHeader(last.Header) {
|
for _, c := range auth.ParseAuthHeader(last.Header) {
|
||||||
if c.scheme == bearerAuth {
|
if c.Scheme == auth.BearerAuth {
|
||||||
if err := invalidAuthorization(c, responses); err != nil {
|
if err := invalidAuthorization(c, responses); err != nil {
|
||||||
delete(a.handlers, host)
|
delete(a.handlers, host)
|
||||||
return err
|
return err
|
||||||
|
@ -152,26 +148,35 @@ func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.R
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
common, err := a.generateTokenOptions(ctx, host, c)
|
var username, secret string
|
||||||
|
if a.credentials != nil {
|
||||||
|
var err error
|
||||||
|
username, secret, err = a.credentials(host)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
common, err := auth.GenerateTokenOptions(ctx, host, username, secret, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
a.handlers[host] = newAuthHandler(a.client, a.header, c.scheme, common)
|
a.handlers[host] = newAuthHandler(a.client, a.header, c.Scheme, common)
|
||||||
return nil
|
return nil
|
||||||
} else if c.scheme == basicAuth && a.credentials != nil {
|
} else if c.Scheme == auth.BasicAuth && a.credentials != nil {
|
||||||
username, secret, err := a.credentials(host)
|
username, secret, err := a.credentials(host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if username != "" && secret != "" {
|
if username != "" && secret != "" {
|
||||||
common := tokenOptions{
|
common := auth.TokenOptions{
|
||||||
username: username,
|
Username: username,
|
||||||
secret: secret,
|
Secret: secret,
|
||||||
}
|
}
|
||||||
|
|
||||||
a.handlers[host] = newAuthHandler(a.client, a.header, c.scheme, common)
|
a.handlers[host] = newAuthHandler(a.client, a.header, c.Scheme, common)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,38 +184,6 @@ func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.R
|
||||||
return errors.Wrap(errdefs.ErrNotImplemented, "failed to find supported auth scheme")
|
return errors.Wrap(errdefs.ErrNotImplemented, "failed to find supported auth scheme")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *dockerAuthorizer) generateTokenOptions(ctx context.Context, host string, c challenge) (tokenOptions, error) {
|
|
||||||
realm, ok := c.parameters["realm"]
|
|
||||||
if !ok {
|
|
||||||
return tokenOptions{}, errors.New("no realm specified for token auth challenge")
|
|
||||||
}
|
|
||||||
|
|
||||||
realmURL, err := url.Parse(realm)
|
|
||||||
if err != nil {
|
|
||||||
return tokenOptions{}, errors.Wrap(err, "invalid token auth challenge realm")
|
|
||||||
}
|
|
||||||
|
|
||||||
to := tokenOptions{
|
|
||||||
realm: realmURL.String(),
|
|
||||||
service: c.parameters["service"],
|
|
||||||
}
|
|
||||||
|
|
||||||
scope, ok := c.parameters["scope"]
|
|
||||||
if ok {
|
|
||||||
to.scopes = append(to.scopes, scope)
|
|
||||||
} else {
|
|
||||||
log.G(ctx).WithField("host", host).Debug("no scope specified for token auth challenge")
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.credentials != nil {
|
|
||||||
to.username, to.secret, err = a.credentials(host)
|
|
||||||
if err != nil {
|
|
||||||
return tokenOptions{}, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return to, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// authResult is used to control limit rate.
|
// authResult is used to control limit rate.
|
||||||
type authResult struct {
|
type authResult struct {
|
||||||
sync.WaitGroup
|
sync.WaitGroup
|
||||||
|
@ -227,17 +200,17 @@ type authHandler struct {
|
||||||
client *http.Client
|
client *http.Client
|
||||||
|
|
||||||
// only support basic and bearer schemes
|
// only support basic and bearer schemes
|
||||||
scheme authenticationScheme
|
scheme auth.AuthenticationScheme
|
||||||
|
|
||||||
// common contains common challenge answer
|
// common contains common challenge answer
|
||||||
common tokenOptions
|
common auth.TokenOptions
|
||||||
|
|
||||||
// scopedTokens caches token indexed by scopes, which used in
|
// scopedTokens caches token indexed by scopes, which used in
|
||||||
// bearer auth case
|
// bearer auth case
|
||||||
scopedTokens map[string]*authResult
|
scopedTokens map[string]*authResult
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAuthHandler(client *http.Client, hdr http.Header, scheme authenticationScheme, opts tokenOptions) *authHandler {
|
func newAuthHandler(client *http.Client, hdr http.Header, scheme auth.AuthenticationScheme, opts auth.TokenOptions) *authHandler {
|
||||||
return &authHandler{
|
return &authHandler{
|
||||||
header: hdr,
|
header: hdr,
|
||||||
client: client,
|
client: client,
|
||||||
|
@ -249,17 +222,17 @@ func newAuthHandler(client *http.Client, hdr http.Header, scheme authenticationS
|
||||||
|
|
||||||
func (ah *authHandler) authorize(ctx context.Context) (string, error) {
|
func (ah *authHandler) authorize(ctx context.Context) (string, error) {
|
||||||
switch ah.scheme {
|
switch ah.scheme {
|
||||||
case basicAuth:
|
case auth.BasicAuth:
|
||||||
return ah.doBasicAuth(ctx)
|
return ah.doBasicAuth(ctx)
|
||||||
case bearerAuth:
|
case auth.BearerAuth:
|
||||||
return ah.doBearerAuth(ctx)
|
return ah.doBearerAuth(ctx)
|
||||||
default:
|
default:
|
||||||
return "", errors.Wrap(errdefs.ErrNotImplemented, "failed to find supported auth scheme")
|
return "", errors.Wrapf(errdefs.ErrNotImplemented, "failed to find supported auth scheme: %s", string(ah.scheme))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ah *authHandler) doBasicAuth(ctx context.Context) (string, error) {
|
func (ah *authHandler) doBasicAuth(ctx context.Context) (string, error) {
|
||||||
username, secret := ah.common.username, ah.common.secret
|
username, secret := ah.common.Username, ah.common.Secret
|
||||||
|
|
||||||
if username == "" || secret == "" {
|
if username == "" || secret == "" {
|
||||||
return "", fmt.Errorf("failed to handle basic auth because missing username or secret")
|
return "", fmt.Errorf("failed to handle basic auth because missing username or secret")
|
||||||
|
@ -269,14 +242,14 @@ func (ah *authHandler) doBasicAuth(ctx context.Context) (string, error) {
|
||||||
return fmt.Sprintf("Basic %s", auth), nil
|
return fmt.Sprintf("Basic %s", auth), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ah *authHandler) doBearerAuth(ctx context.Context) (string, error) {
|
func (ah *authHandler) doBearerAuth(ctx context.Context) (token string, err error) {
|
||||||
// copy common tokenOptions
|
// copy common tokenOptions
|
||||||
to := ah.common
|
to := ah.common
|
||||||
|
|
||||||
to.scopes = GetTokenScopes(ctx, to.scopes)
|
to.Scopes = GetTokenScopes(ctx, to.Scopes)
|
||||||
|
|
||||||
// Docs: https://docs.docker.com/registry/spec/auth/scope
|
// Docs: https://docs.docker.com/registry/spec/auth/scope
|
||||||
scoped := strings.Join(to.scopes, " ")
|
scoped := strings.Join(to.Scopes, " ")
|
||||||
|
|
||||||
ah.Lock()
|
ah.Lock()
|
||||||
if r, exist := ah.scopedTokens[scoped]; exist {
|
if r, exist := ah.scopedTokens[scoped]; exist {
|
||||||
|
@ -291,174 +264,52 @@ func (ah *authHandler) doBearerAuth(ctx context.Context) (string, error) {
|
||||||
ah.scopedTokens[scoped] = r
|
ah.scopedTokens[scoped] = r
|
||||||
ah.Unlock()
|
ah.Unlock()
|
||||||
|
|
||||||
// fetch token for the resource scope
|
defer func() {
|
||||||
var (
|
|
||||||
token string
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
if to.secret != "" {
|
|
||||||
// credential information is provided, use oauth POST endpoint
|
|
||||||
token, err = ah.fetchTokenWithOAuth(ctx, to)
|
|
||||||
err = errors.Wrap(err, "failed to fetch oauth token")
|
|
||||||
} else {
|
|
||||||
// do request anonymously
|
|
||||||
token, err = ah.fetchToken(ctx, to)
|
|
||||||
err = errors.Wrap(err, "failed to fetch anonymous token")
|
|
||||||
}
|
|
||||||
token = fmt.Sprintf("Bearer %s", token)
|
token = fmt.Sprintf("Bearer %s", token)
|
||||||
|
|
||||||
r.token, r.err = token, err
|
r.token, r.err = token, err
|
||||||
r.Done()
|
r.Done()
|
||||||
return r.token, r.err
|
}()
|
||||||
}
|
|
||||||
|
|
||||||
type tokenOptions struct {
|
// fetch token for the resource scope
|
||||||
realm string
|
if to.Secret != "" {
|
||||||
service string
|
defer func() {
|
||||||
scopes []string
|
err = errors.Wrap(err, "failed to fetch oauth token")
|
||||||
username string
|
}()
|
||||||
secret string
|
// credential information is provided, use oauth POST endpoint
|
||||||
}
|
|
||||||
|
|
||||||
type postTokenResponse struct {
|
|
||||||
AccessToken string `json:"access_token"`
|
|
||||||
RefreshToken string `json:"refresh_token"`
|
|
||||||
ExpiresIn int `json:"expires_in"`
|
|
||||||
IssuedAt time.Time `json:"issued_at"`
|
|
||||||
Scope string `json:"scope"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ah *authHandler) fetchTokenWithOAuth(ctx context.Context, to tokenOptions) (string, error) {
|
|
||||||
form := url.Values{}
|
|
||||||
if len(to.scopes) > 0 {
|
|
||||||
form.Set("scope", strings.Join(to.scopes, " "))
|
|
||||||
}
|
|
||||||
form.Set("service", to.service)
|
|
||||||
// TODO: Allow setting client_id
|
// TODO: Allow setting client_id
|
||||||
form.Set("client_id", "containerd-client")
|
resp, err := auth.FetchTokenWithOAuth(ctx, ah.client, ah.header, "containerd-client", to)
|
||||||
|
|
||||||
if to.username == "" {
|
|
||||||
form.Set("grant_type", "refresh_token")
|
|
||||||
form.Set("refresh_token", to.secret)
|
|
||||||
} else {
|
|
||||||
form.Set("grant_type", "password")
|
|
||||||
form.Set("username", to.username)
|
|
||||||
form.Set("password", to.secret)
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", to.realm, strings.NewReader(form.Encode()))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
var errStatus remoteerrors.ErrUnexpectedStatus
|
||||||
}
|
if errors.As(err, &errStatus) {
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
|
|
||||||
if ah.header != nil {
|
|
||||||
for k, v := range ah.header {
|
|
||||||
req.Header[k] = append(req.Header[k], v...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := ctxhttp.Do(ctx, ah.client, req)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
// Registries without support for POST may return 404 for POST /v2/token.
|
// Registries without support for POST may return 404 for POST /v2/token.
|
||||||
// As of September 2017, GCR is known to return 404.
|
// As of September 2017, GCR is known to return 404.
|
||||||
// As of February 2018, JFrog Artifactory is known to return 401.
|
// As of February 2018, JFrog Artifactory is known to return 401.
|
||||||
if (resp.StatusCode == 405 && to.username != "") || resp.StatusCode == 404 || resp.StatusCode == 401 {
|
if (errStatus.StatusCode == 405 && to.Username != "") || errStatus.StatusCode == 404 || errStatus.StatusCode == 401 {
|
||||||
return ah.fetchToken(ctx, to)
|
resp, err := auth.FetchToken(ctx, ah.client, ah.header, to)
|
||||||
} else if resp.StatusCode < 200 || resp.StatusCode >= 400 {
|
if err != nil {
|
||||||
b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
|
return "", err
|
||||||
|
}
|
||||||
|
return resp.Token, nil
|
||||||
|
}
|
||||||
log.G(ctx).WithFields(logrus.Fields{
|
log.G(ctx).WithFields(logrus.Fields{
|
||||||
"status": resp.Status,
|
"status": errStatus.Status,
|
||||||
"body": string(b),
|
"body": string(errStatus.Body),
|
||||||
}).Debugf("token request failed")
|
}).Debugf("token request failed")
|
||||||
// TODO: handle error body and write debug output
|
|
||||||
return "", errors.Errorf("unexpected status: %s", resp.Status)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
decoder := json.NewDecoder(resp.Body)
|
|
||||||
|
|
||||||
var tr postTokenResponse
|
|
||||||
if err = decoder.Decode(&tr); err != nil {
|
|
||||||
return "", fmt.Errorf("unable to decode token response: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return tr.AccessToken, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type getTokenResponse struct {
|
|
||||||
Token string `json:"token"`
|
|
||||||
AccessToken string `json:"access_token"`
|
|
||||||
ExpiresIn int `json:"expires_in"`
|
|
||||||
IssuedAt time.Time `json:"issued_at"`
|
|
||||||
RefreshToken string `json:"refresh_token"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// fetchToken fetches a token using a GET request
|
|
||||||
func (ah *authHandler) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
|
|
||||||
req, err := http.NewRequest("GET", to.realm, nil)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
return resp.AccessToken, nil
|
||||||
if ah.header != nil {
|
|
||||||
for k, v := range ah.header {
|
|
||||||
req.Header[k] = append(req.Header[k], v...)
|
|
||||||
}
|
}
|
||||||
}
|
// do request anonymously
|
||||||
|
resp, err := auth.FetchToken(ctx, ah.client, ah.header, to)
|
||||||
reqParams := req.URL.Query()
|
|
||||||
|
|
||||||
if to.service != "" {
|
|
||||||
reqParams.Add("service", to.service)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, scope := range to.scopes {
|
|
||||||
reqParams.Add("scope", scope)
|
|
||||||
}
|
|
||||||
|
|
||||||
if to.secret != "" {
|
|
||||||
req.SetBasicAuth(to.username, to.secret)
|
|
||||||
}
|
|
||||||
|
|
||||||
req.URL.RawQuery = reqParams.Encode()
|
|
||||||
|
|
||||||
resp, err := ctxhttp.Do(ctx, ah.client, req)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.Wrap(err, "failed to fetch anonymous token")
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
return resp.Token, nil
|
||||||
|
|
||||||
if resp.StatusCode < 200 || resp.StatusCode >= 400 {
|
|
||||||
// TODO: handle error body and write debug output
|
|
||||||
return "", errors.Errorf("unexpected status: %s", resp.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
decoder := json.NewDecoder(resp.Body)
|
|
||||||
|
|
||||||
var tr getTokenResponse
|
|
||||||
if err = decoder.Decode(&tr); err != nil {
|
|
||||||
return "", fmt.Errorf("unable to decode token response: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// `access_token` is equivalent to `token` and if both are specified
|
|
||||||
// the choice is undefined. Canonicalize `access_token` by sticking
|
|
||||||
// things in `token`.
|
|
||||||
if tr.AccessToken != "" {
|
|
||||||
tr.Token = tr.AccessToken
|
|
||||||
}
|
|
||||||
|
|
||||||
if tr.Token == "" {
|
|
||||||
return "", ErrNoToken
|
|
||||||
}
|
|
||||||
|
|
||||||
return tr.Token, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func invalidAuthorization(c challenge, responses []*http.Response) error {
|
func invalidAuthorization(c auth.Challenge, responses []*http.Response) error {
|
||||||
errStr := c.parameters["error"]
|
errStr := c.Parameters["error"]
|
||||||
if errStr == "" {
|
if errStr == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
16
vendor/github.com/containerd/containerd/remotes/docker/pusher.go
generated
vendored
16
vendor/github.com/containerd/containerd/remotes/docker/pusher.go
generated
vendored
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/remotes"
|
"github.com/containerd/containerd/remotes"
|
||||||
|
remoteserrors "github.com/containerd/containerd/remotes/errors"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -112,8 +113,9 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
||||||
return nil, errors.Wrapf(errdefs.ErrAlreadyExists, "content %v on remote", desc.Digest)
|
return nil, errors.Wrapf(errdefs.ErrAlreadyExists, "content %v on remote", desc.Digest)
|
||||||
}
|
}
|
||||||
} else if resp.StatusCode != http.StatusNotFound {
|
} else if resp.StatusCode != http.StatusNotFound {
|
||||||
// TODO: log error
|
err := remoteserrors.NewUnexpectedStatusErr(resp)
|
||||||
return nil, errors.Errorf("unexpected response: %s", resp.Status)
|
log.G(ctx).WithField("resp", resp).WithField("body", string(err.(remoteserrors.ErrUnexpectedStatus).Body)).Debug("unexpected response")
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,8 +168,9 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
||||||
})
|
})
|
||||||
return nil, errors.Wrapf(errdefs.ErrAlreadyExists, "content %v on remote", desc.Digest)
|
return nil, errors.Wrapf(errdefs.ErrAlreadyExists, "content %v on remote", desc.Digest)
|
||||||
default:
|
default:
|
||||||
// TODO: log error
|
err := remoteserrors.NewUnexpectedStatusErr(resp)
|
||||||
return nil, errors.Errorf("unexpected response: %s", resp.Status)
|
log.G(ctx).WithField("resp", resp).WithField("body", string(err.(remoteserrors.ErrUnexpectedStatus).Body)).Debug("unexpected response")
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -244,8 +247,9 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
||||||
switch resp.StatusCode {
|
switch resp.StatusCode {
|
||||||
case http.StatusOK, http.StatusCreated, http.StatusNoContent:
|
case http.StatusOK, http.StatusCreated, http.StatusNoContent:
|
||||||
default:
|
default:
|
||||||
// TODO: log error
|
err := remoteserrors.NewUnexpectedStatusErr(resp)
|
||||||
pr.CloseWithError(errors.Errorf("unexpected response: %s", resp.Status))
|
log.G(ctx).WithField("resp", resp).WithField("body", string(err.(remoteserrors.ErrUnexpectedStatus).Body)).Debug("unexpected response")
|
||||||
|
pr.CloseWithError(err)
|
||||||
}
|
}
|
||||||
respC <- resp
|
respC <- resp
|
||||||
}()
|
}()
|
||||||
|
|
4
vendor/github.com/containerd/containerd/remotes/docker/resolver.go
generated
vendored
4
vendor/github.com/containerd/containerd/remotes/docker/resolver.go
generated
vendored
|
@ -41,10 +41,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrNoToken is returned if a request is successful but the body does not
|
|
||||||
// contain an authorization token.
|
|
||||||
ErrNoToken = errors.New("authorization server did not include a token in the response")
|
|
||||||
|
|
||||||
// ErrInvalidAuthorization is used when credentials are passed to a server but
|
// ErrInvalidAuthorization is used when credentials are passed to a server but
|
||||||
// those credentials are rejected.
|
// those credentials are rejected.
|
||||||
ErrInvalidAuthorization = errors.New("authorization failed")
|
ErrInvalidAuthorization = errors.New("authorization failed")
|
||||||
|
|
46
vendor/github.com/containerd/containerd/remotes/errors/errors.go
generated
vendored
Normal file
46
vendor/github.com/containerd/containerd/remotes/errors/errors.go
generated
vendored
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ error = ErrUnexpectedStatus{}
|
||||||
|
|
||||||
|
// ErrUnexpectedStatus is returned if a registry API request returned with unexpected HTTP status
|
||||||
|
type ErrUnexpectedStatus struct {
|
||||||
|
Status string
|
||||||
|
StatusCode int
|
||||||
|
Body []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ErrUnexpectedStatus) Error() string {
|
||||||
|
return fmt.Sprintf("unexpected status: %s", e.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewUnexpectedStatusErr creates an ErrUnexpectedStatus from HTTP response
|
||||||
|
func NewUnexpectedStatusErr(resp *http.Response) error {
|
||||||
|
var b []byte
|
||||||
|
if resp.Body != nil {
|
||||||
|
b, _ = ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
|
||||||
|
}
|
||||||
|
return ErrUnexpectedStatus{Status: resp.Status, StatusCode: resp.StatusCode, Body: b}
|
||||||
|
}
|
19
vendor/github.com/containerd/containerd/runtime/v1/shim/client/client.go
generated
vendored
19
vendor/github.com/containerd/containerd/runtime/v1/shim/client/client.go
generated
vendored
|
@ -22,7 +22,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -68,24 +67,22 @@ func WithStart(binary, address, daemonAddress, cgroup string, debug bool, exitHa
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
stdoutCopy := ioutil.Discard
|
var stdoutLog io.ReadWriteCloser
|
||||||
stderrCopy := ioutil.Discard
|
var stderrLog io.ReadWriteCloser
|
||||||
stdoutLog, err := v1.OpenShimStdoutLog(ctx, config.WorkDir)
|
if debug {
|
||||||
|
stdoutLog, err = v1.OpenShimStdoutLog(ctx, config.WorkDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrapf(err, "failed to create stdout log")
|
return nil, nil, errors.Wrapf(err, "failed to create stdout log")
|
||||||
}
|
}
|
||||||
|
|
||||||
stderrLog, err := v1.OpenShimStderrLog(ctx, config.WorkDir)
|
stderrLog, err = v1.OpenShimStderrLog(ctx, config.WorkDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrapf(err, "failed to create stderr log")
|
return nil, nil, errors.Wrapf(err, "failed to create stderr log")
|
||||||
}
|
}
|
||||||
if debug {
|
|
||||||
stdoutCopy = os.Stdout
|
|
||||||
stderrCopy = os.Stderr
|
|
||||||
}
|
|
||||||
|
|
||||||
go io.Copy(stdoutCopy, stdoutLog)
|
go io.Copy(os.Stdout, stdoutLog)
|
||||||
go io.Copy(stderrCopy, stderrLog)
|
go io.Copy(os.Stderr, stderrLog)
|
||||||
|
}
|
||||||
|
|
||||||
cmd, err := newCommand(binary, daemonAddress, debug, config, f, stdoutLog, stderrLog)
|
cmd, err := newCommand(binary, daemonAddress, debug, config, f, stdoutLog, stderrLog)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
3
vendor/github.com/containerd/containerd/vendor.conf
generated
vendored
3
vendor/github.com/containerd/containerd/vendor.conf
generated
vendored
|
@ -7,6 +7,7 @@ github.com/containerd/console v1.0.0
|
||||||
github.com/containerd/continuity efbc4488d8fe1bdc16bde3b2d2990d9b3a899165
|
github.com/containerd/continuity efbc4488d8fe1bdc16bde3b2d2990d9b3a899165
|
||||||
github.com/containerd/fifo f15a3290365b9d2627d189e619ab4008e0069caf
|
github.com/containerd/fifo f15a3290365b9d2627d189e619ab4008e0069caf
|
||||||
github.com/containerd/go-runc 7016d3ce2328dd2cb1192b2076ebd565c4e8df0c
|
github.com/containerd/go-runc 7016d3ce2328dd2cb1192b2076ebd565c4e8df0c
|
||||||
|
github.com/containerd/nri 0afc7f031eaf9c7d9c1a381b7ab5462e89c998fc
|
||||||
github.com/containerd/ttrpc v1.0.1
|
github.com/containerd/ttrpc v1.0.1
|
||||||
github.com/containerd/typeurl v1.0.1
|
github.com/containerd/typeurl v1.0.1
|
||||||
github.com/coreos/go-systemd/v22 v22.1.0
|
github.com/coreos/go-systemd/v22 v22.1.0
|
||||||
|
@ -57,7 +58,7 @@ gotest.tools/v3 v3.0.2
|
||||||
github.com/cilium/ebpf 1c8d4c9ef7759622653a1d319284a44652333b28
|
github.com/cilium/ebpf 1c8d4c9ef7759622653a1d319284a44652333b28
|
||||||
|
|
||||||
# cri dependencies
|
# cri dependencies
|
||||||
github.com/containerd/cri 4e6644c8cf7fb825f62e0007421b7d83dfeab5a1 # master
|
github.com/containerd/cri 35e623e6bf7512e8c82b8ac6052cb1d720189f28 # master
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/docker/docker 4634ce647cf2ce2c6031129ccd109e557244986f
|
github.com/docker/docker 4634ce647cf2ce2c6031129ccd109e557244986f
|
||||||
github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528
|
github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528
|
||||||
|
|
2
vendor/github.com/containerd/containerd/version/version.go
generated
vendored
2
vendor/github.com/containerd/containerd/version/version.go
generated
vendored
|
@ -23,7 +23,7 @@ var (
|
||||||
Package = "github.com/containerd/containerd"
|
Package = "github.com/containerd/containerd"
|
||||||
|
|
||||||
// Version holds the complete version number. Filled in at linking time.
|
// Version holds the complete version number. Filled in at linking time.
|
||||||
Version = "1.4.1+unknown"
|
Version = "1.4.0+unknown"
|
||||||
|
|
||||||
// Revision is filled with the VCS (e.g. git) revision being used to build
|
// Revision is filled with the VCS (e.g. git) revision being used to build
|
||||||
// the program at linking time.
|
// the program at linking time.
|
||||||
|
|
9
vendor/github.com/containerd/go-runc/go.mod
generated
vendored
9
vendor/github.com/containerd/go-runc/go.mod
generated
vendored
|
@ -3,8 +3,9 @@ module github.com/containerd/go-runc
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e
|
github.com/containerd/console v1.0.1
|
||||||
github.com/opencontainers/runtime-spec v1.0.1
|
github.com/opencontainers/runtime-spec v1.0.2
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.9.1
|
||||||
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449
|
github.com/sirupsen/logrus v1.7.0
|
||||||
|
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f
|
||||||
)
|
)
|
||||||
|
|
20
vendor/github.com/containerd/go-runc/io_unix.go
generated
vendored
20
vendor/github.com/containerd/go-runc/io_unix.go
generated
vendored
|
@ -20,7 +20,9 @@ package runc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
"runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewPipeIO creates pipe pairs to be used with runc
|
// NewPipeIO creates pipe pairs to be used with runc
|
||||||
|
@ -47,27 +49,45 @@ func NewPipeIO(uid, gid int, opts ...IOOpt) (i IO, err error) {
|
||||||
}
|
}
|
||||||
pipes = append(pipes, stdin)
|
pipes = append(pipes, stdin)
|
||||||
if err = unix.Fchown(int(stdin.r.Fd()), uid, gid); err != nil {
|
if err = unix.Fchown(int(stdin.r.Fd()), uid, gid); err != nil {
|
||||||
|
// TODO: revert with proper darwin solution, skipping for now
|
||||||
|
// as darwin chown is returning EINVAL on anonymous pipe
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
logrus.WithError(err).Debug("failed to chown stdin, ignored")
|
||||||
|
} else {
|
||||||
return nil, errors.Wrap(err, "failed to chown stdin")
|
return nil, errors.Wrap(err, "failed to chown stdin")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if option.OpenStdout {
|
if option.OpenStdout {
|
||||||
if stdout, err = newPipe(); err != nil {
|
if stdout, err = newPipe(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
pipes = append(pipes, stdout)
|
pipes = append(pipes, stdout)
|
||||||
if err = unix.Fchown(int(stdout.w.Fd()), uid, gid); err != nil {
|
if err = unix.Fchown(int(stdout.w.Fd()), uid, gid); err != nil {
|
||||||
|
// TODO: revert with proper darwin solution, skipping for now
|
||||||
|
// as darwin chown is returning EINVAL on anonymous pipe
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
logrus.WithError(err).Debug("failed to chown stdout, ignored")
|
||||||
|
} else {
|
||||||
return nil, errors.Wrap(err, "failed to chown stdout")
|
return nil, errors.Wrap(err, "failed to chown stdout")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if option.OpenStderr {
|
if option.OpenStderr {
|
||||||
if stderr, err = newPipe(); err != nil {
|
if stderr, err = newPipe(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
pipes = append(pipes, stderr)
|
pipes = append(pipes, stderr)
|
||||||
if err = unix.Fchown(int(stderr.w.Fd()), uid, gid); err != nil {
|
if err = unix.Fchown(int(stderr.w.Fd()), uid, gid); err != nil {
|
||||||
|
// TODO: revert with proper darwin solution, skipping for now
|
||||||
|
// as darwin chown is returning EINVAL on anonymous pipe
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
logrus.WithError(err).Debug("failed to chown stderr, ignored")
|
||||||
|
} else {
|
||||||
return nil, errors.Wrap(err, "failed to chown stderr")
|
return nil, errors.Wrap(err, "failed to chown stderr")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return &pipeIO{
|
return &pipeIO{
|
||||||
in: stdin,
|
in: stdin,
|
||||||
out: stdout,
|
out: stdout,
|
||||||
|
|
94
vendor/github.com/containerd/go-runc/runc.go
generated
vendored
94
vendor/github.com/containerd/go-runc/runc.go
generated
vendored
|
@ -29,7 +29,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
@ -55,24 +54,9 @@ const (
|
||||||
DefaultCommand = "runc"
|
DefaultCommand = "runc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Runc is the client to the runc cli
|
|
||||||
type Runc struct {
|
|
||||||
//If command is empty, DefaultCommand is used
|
|
||||||
Command string
|
|
||||||
Root string
|
|
||||||
Debug bool
|
|
||||||
Log string
|
|
||||||
LogFormat Format
|
|
||||||
PdeathSignal syscall.Signal
|
|
||||||
Setpgid bool
|
|
||||||
Criu string
|
|
||||||
SystemdCgroup bool
|
|
||||||
Rootless *bool // nil stands for "auto"
|
|
||||||
}
|
|
||||||
|
|
||||||
// List returns all containers created inside the provided runc root directory
|
// List returns all containers created inside the provided runc root directory
|
||||||
func (r *Runc) List(context context.Context) ([]*Container, error) {
|
func (r *Runc) List(context context.Context) ([]*Container, error) {
|
||||||
data, err := cmdOutput(r.command(context, "list", "--format=json"), false)
|
data, err := cmdOutput(r.command(context, "list", "--format=json"), false, nil)
|
||||||
defer putBuf(data)
|
defer putBuf(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -86,7 +70,7 @@ func (r *Runc) List(context context.Context) ([]*Container, error) {
|
||||||
|
|
||||||
// State returns the state for the container provided by id
|
// State returns the state for the container provided by id
|
||||||
func (r *Runc) State(context context.Context, id string) (*Container, error) {
|
func (r *Runc) State(context context.Context, id string) (*Container, error) {
|
||||||
data, err := cmdOutput(r.command(context, "state", id), true)
|
data, err := cmdOutput(r.command(context, "state", id), true, nil)
|
||||||
defer putBuf(data)
|
defer putBuf(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s: %s", err, data.String())
|
return nil, fmt.Errorf("%s: %s", err, data.String())
|
||||||
|
@ -111,6 +95,7 @@ type CreateOpts struct {
|
||||||
NoPivot bool
|
NoPivot bool
|
||||||
NoNewKeyring bool
|
NoNewKeyring bool
|
||||||
ExtraFiles []*os.File
|
ExtraFiles []*os.File
|
||||||
|
Started chan<- int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *CreateOpts) args() (out []string, err error) {
|
func (o *CreateOpts) args() (out []string, err error) {
|
||||||
|
@ -156,7 +141,7 @@ func (r *Runc) Create(context context.Context, id, bundle string, opts *CreateOp
|
||||||
cmd.ExtraFiles = opts.ExtraFiles
|
cmd.ExtraFiles = opts.ExtraFiles
|
||||||
|
|
||||||
if cmd.Stdout == nil && cmd.Stderr == nil {
|
if cmd.Stdout == nil && cmd.Stderr == nil {
|
||||||
data, err := cmdOutput(cmd, true)
|
data, err := cmdOutput(cmd, true, nil)
|
||||||
defer putBuf(data)
|
defer putBuf(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s: %s", err, data.String())
|
return fmt.Errorf("%s: %s", err, data.String())
|
||||||
|
@ -176,7 +161,7 @@ func (r *Runc) Create(context context.Context, id, bundle string, opts *CreateOp
|
||||||
}
|
}
|
||||||
status, err := Monitor.Wait(cmd, ec)
|
status, err := Monitor.Wait(cmd, ec)
|
||||||
if err == nil && status != 0 {
|
if err == nil && status != 0 {
|
||||||
err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
|
err = fmt.Errorf("%s did not terminate successfully: %w", cmd.Args[0], &ExitError{status})
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -191,6 +176,7 @@ type ExecOpts struct {
|
||||||
PidFile string
|
PidFile string
|
||||||
ConsoleSocket ConsoleSocket
|
ConsoleSocket ConsoleSocket
|
||||||
Detach bool
|
Detach bool
|
||||||
|
Started chan<- int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *ExecOpts) args() (out []string, err error) {
|
func (o *ExecOpts) args() (out []string, err error) {
|
||||||
|
@ -210,9 +196,12 @@ func (o *ExecOpts) args() (out []string, err error) {
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec executres and additional process inside the container based on a full
|
// Exec executes an additional process inside the container based on a full
|
||||||
// OCI Process specification
|
// OCI Process specification
|
||||||
func (r *Runc) Exec(context context.Context, id string, spec specs.Process, opts *ExecOpts) error {
|
func (r *Runc) Exec(context context.Context, id string, spec specs.Process, opts *ExecOpts) error {
|
||||||
|
if opts.Started != nil {
|
||||||
|
defer close(opts.Started)
|
||||||
|
}
|
||||||
f, err := ioutil.TempFile(os.Getenv("XDG_RUNTIME_DIR"), "runc-process")
|
f, err := ioutil.TempFile(os.Getenv("XDG_RUNTIME_DIR"), "runc-process")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -236,10 +225,10 @@ func (r *Runc) Exec(context context.Context, id string, spec specs.Process, opts
|
||||||
opts.Set(cmd)
|
opts.Set(cmd)
|
||||||
}
|
}
|
||||||
if cmd.Stdout == nil && cmd.Stderr == nil {
|
if cmd.Stdout == nil && cmd.Stderr == nil {
|
||||||
data, err := cmdOutput(cmd, true)
|
data, err := cmdOutput(cmd, true, opts.Started)
|
||||||
defer putBuf(data)
|
defer putBuf(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s: %s", err, data.String())
|
return fmt.Errorf("%w: %s", err, data.String())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -247,6 +236,9 @@ func (r *Runc) Exec(context context.Context, id string, spec specs.Process, opts
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if opts.Started != nil {
|
||||||
|
opts.Started <- cmd.Process.Pid
|
||||||
|
}
|
||||||
if opts != nil && opts.IO != nil {
|
if opts != nil && opts.IO != nil {
|
||||||
if c, ok := opts.IO.(StartCloser); ok {
|
if c, ok := opts.IO.(StartCloser); ok {
|
||||||
if err := c.CloseAfterStart(); err != nil {
|
if err := c.CloseAfterStart(); err != nil {
|
||||||
|
@ -256,7 +248,7 @@ func (r *Runc) Exec(context context.Context, id string, spec specs.Process, opts
|
||||||
}
|
}
|
||||||
status, err := Monitor.Wait(cmd, ec)
|
status, err := Monitor.Wait(cmd, ec)
|
||||||
if err == nil && status != 0 {
|
if err == nil && status != 0 {
|
||||||
err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
|
err = fmt.Errorf("%s did not terminate successfully: %w", cmd.Args[0], &ExitError{status})
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -264,6 +256,9 @@ func (r *Runc) Exec(context context.Context, id string, spec specs.Process, opts
|
||||||
// Run runs the create, start, delete lifecycle of the container
|
// Run runs the create, start, delete lifecycle of the container
|
||||||
// and returns its exit status after it has exited
|
// and returns its exit status after it has exited
|
||||||
func (r *Runc) Run(context context.Context, id, bundle string, opts *CreateOpts) (int, error) {
|
func (r *Runc) Run(context context.Context, id, bundle string, opts *CreateOpts) (int, error) {
|
||||||
|
if opts.Started != nil {
|
||||||
|
defer close(opts.Started)
|
||||||
|
}
|
||||||
args := []string{"run", "--bundle", bundle}
|
args := []string{"run", "--bundle", bundle}
|
||||||
if opts != nil {
|
if opts != nil {
|
||||||
oargs, err := opts.args()
|
oargs, err := opts.args()
|
||||||
|
@ -280,9 +275,12 @@ func (r *Runc) Run(context context.Context, id, bundle string, opts *CreateOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
if opts.Started != nil {
|
||||||
|
opts.Started <- cmd.Process.Pid
|
||||||
|
}
|
||||||
status, err := Monitor.Wait(cmd, ec)
|
status, err := Monitor.Wait(cmd, ec)
|
||||||
if err == nil && status != 0 {
|
if err == nil && status != 0 {
|
||||||
err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
|
err = fmt.Errorf("%s did not terminate successfully: %w", cmd.Args[0], &ExitError{status})
|
||||||
}
|
}
|
||||||
return status, err
|
return status, err
|
||||||
}
|
}
|
||||||
|
@ -403,7 +401,7 @@ func (r *Runc) Resume(context context.Context, id string) error {
|
||||||
|
|
||||||
// Ps lists all the processes inside the container returning their pids
|
// Ps lists all the processes inside the container returning their pids
|
||||||
func (r *Runc) Ps(context context.Context, id string) ([]int, error) {
|
func (r *Runc) Ps(context context.Context, id string) ([]int, error) {
|
||||||
data, err := cmdOutput(r.command(context, "ps", "--format", "json", id), true)
|
data, err := cmdOutput(r.command(context, "ps", "--format", "json", id), true, nil)
|
||||||
defer putBuf(data)
|
defer putBuf(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s: %s", err, data.String())
|
return nil, fmt.Errorf("%s: %s", err, data.String())
|
||||||
|
@ -417,7 +415,7 @@ func (r *Runc) Ps(context context.Context, id string) ([]int, error) {
|
||||||
|
|
||||||
// Top lists all the processes inside the container returning the full ps data
|
// Top lists all the processes inside the container returning the full ps data
|
||||||
func (r *Runc) Top(context context.Context, id string, psOptions string) (*TopResults, error) {
|
func (r *Runc) Top(context context.Context, id string, psOptions string) (*TopResults, error) {
|
||||||
data, err := cmdOutput(r.command(context, "ps", "--format", "table", id, psOptions), true)
|
data, err := cmdOutput(r.command(context, "ps", "--format", "table", id, psOptions), true, nil)
|
||||||
defer putBuf(data)
|
defer putBuf(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s: %s", err, data.String())
|
return nil, fmt.Errorf("%s: %s", err, data.String())
|
||||||
|
@ -452,6 +450,10 @@ type CheckpointOpts struct {
|
||||||
// EmptyNamespaces creates a namespace for the container but does not save its properties
|
// EmptyNamespaces creates a namespace for the container but does not save its properties
|
||||||
// Provide the namespaces you wish to be checkpointed without their settings on restore
|
// Provide the namespaces you wish to be checkpointed without their settings on restore
|
||||||
EmptyNamespaces []string
|
EmptyNamespaces []string
|
||||||
|
// LazyPages uses userfaultfd to lazily restore memory pages
|
||||||
|
LazyPages bool
|
||||||
|
// StatusFile is the file criu writes \0 to once lazy-pages is ready
|
||||||
|
StatusFile *os.File
|
||||||
}
|
}
|
||||||
|
|
||||||
type CgroupMode string
|
type CgroupMode string
|
||||||
|
@ -493,6 +495,9 @@ func (o *CheckpointOpts) args() (out []string) {
|
||||||
for _, ns := range o.EmptyNamespaces {
|
for _, ns := range o.EmptyNamespaces {
|
||||||
out = append(out, "--empty-ns", ns)
|
out = append(out, "--empty-ns", ns)
|
||||||
}
|
}
|
||||||
|
if o.LazyPages {
|
||||||
|
out = append(out, "--lazy-pages")
|
||||||
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,13 +516,23 @@ func PreDump(args []string) []string {
|
||||||
// Checkpoint allows you to checkpoint a container using criu
|
// Checkpoint allows you to checkpoint a container using criu
|
||||||
func (r *Runc) Checkpoint(context context.Context, id string, opts *CheckpointOpts, actions ...CheckpointAction) error {
|
func (r *Runc) Checkpoint(context context.Context, id string, opts *CheckpointOpts, actions ...CheckpointAction) error {
|
||||||
args := []string{"checkpoint"}
|
args := []string{"checkpoint"}
|
||||||
|
extraFiles := []*os.File{}
|
||||||
if opts != nil {
|
if opts != nil {
|
||||||
args = append(args, opts.args()...)
|
args = append(args, opts.args()...)
|
||||||
|
if opts.StatusFile != nil {
|
||||||
|
// pass the status file to the child process
|
||||||
|
extraFiles = []*os.File{opts.StatusFile}
|
||||||
|
// set status-fd to 3 as this will be the file descriptor
|
||||||
|
// of the first file passed with cmd.ExtraFiles
|
||||||
|
args = append(args, "--status-fd", "3")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for _, a := range actions {
|
for _, a := range actions {
|
||||||
args = a(args)
|
args = a(args)
|
||||||
}
|
}
|
||||||
return r.runOrError(r.command(context, append(args, id)...))
|
cmd := r.command(context, append(args, id)...)
|
||||||
|
cmd.ExtraFiles = extraFiles
|
||||||
|
return r.runOrError(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
type RestoreOpts struct {
|
type RestoreOpts struct {
|
||||||
|
@ -583,7 +598,7 @@ func (r *Runc) Restore(context context.Context, id, bundle string, opts *Restore
|
||||||
}
|
}
|
||||||
status, err := Monitor.Wait(cmd, ec)
|
status, err := Monitor.Wait(cmd, ec)
|
||||||
if err == nil && status != 0 {
|
if err == nil && status != 0 {
|
||||||
err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
|
err = fmt.Errorf("%s did not terminate successfully: %w", cmd.Args[0], &ExitError{status})
|
||||||
}
|
}
|
||||||
return status, err
|
return status, err
|
||||||
}
|
}
|
||||||
|
@ -612,7 +627,7 @@ type Version struct {
|
||||||
|
|
||||||
// Version returns the runc and runtime-spec versions
|
// Version returns the runc and runtime-spec versions
|
||||||
func (r *Runc) Version(context context.Context) (Version, error) {
|
func (r *Runc) Version(context context.Context) (Version, error) {
|
||||||
data, err := cmdOutput(r.command(context, "--version"), false)
|
data, err := cmdOutput(r.command(context, "--version"), false, nil)
|
||||||
defer putBuf(data)
|
defer putBuf(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Version{}, err
|
return Version{}, err
|
||||||
|
@ -680,11 +695,11 @@ func (r *Runc) runOrError(cmd *exec.Cmd) error {
|
||||||
}
|
}
|
||||||
status, err := Monitor.Wait(cmd, ec)
|
status, err := Monitor.Wait(cmd, ec)
|
||||||
if err == nil && status != 0 {
|
if err == nil && status != 0 {
|
||||||
err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
|
err = fmt.Errorf("%s did not terminate successfully: %w", cmd.Args[0], &ExitError{status})
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
data, err := cmdOutput(cmd, true)
|
data, err := cmdOutput(cmd, true, nil)
|
||||||
defer putBuf(data)
|
defer putBuf(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s: %s", err, data.String())
|
return fmt.Errorf("%s: %s", err, data.String())
|
||||||
|
@ -694,7 +709,7 @@ func (r *Runc) runOrError(cmd *exec.Cmd) error {
|
||||||
|
|
||||||
// callers of cmdOutput are expected to call putBuf on the returned Buffer
|
// callers of cmdOutput are expected to call putBuf on the returned Buffer
|
||||||
// to ensure it is released back to the shared pool after use.
|
// to ensure it is released back to the shared pool after use.
|
||||||
func cmdOutput(cmd *exec.Cmd, combined bool) (*bytes.Buffer, error) {
|
func cmdOutput(cmd *exec.Cmd, combined bool, started chan<- int) (*bytes.Buffer, error) {
|
||||||
b := getBuf()
|
b := getBuf()
|
||||||
|
|
||||||
cmd.Stdout = b
|
cmd.Stdout = b
|
||||||
|
@ -705,11 +720,22 @@ func cmdOutput(cmd *exec.Cmd, combined bool) (*bytes.Buffer, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if started != nil {
|
||||||
|
started <- cmd.Process.Pid
|
||||||
|
}
|
||||||
|
|
||||||
status, err := Monitor.Wait(cmd, ec)
|
status, err := Monitor.Wait(cmd, ec)
|
||||||
if err == nil && status != 0 {
|
if err == nil && status != 0 {
|
||||||
err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
|
err = fmt.Errorf("%s did not terminate successfully: %w", cmd.Args[0], &ExitError{status})
|
||||||
}
|
}
|
||||||
|
|
||||||
return b, err
|
return b, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExitError struct {
|
||||||
|
Status int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *ExitError) Error() string {
|
||||||
|
return fmt.Sprintf("exit status %d", e.Status)
|
||||||
|
}
|
||||||
|
|
38
vendor/github.com/containerd/go-runc/runc_unix.go
generated
vendored
Normal file
38
vendor/github.com/containerd/go-runc/runc_unix.go
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
//+build !windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package runc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Runc is the client to the runc cli
|
||||||
|
type Runc struct {
|
||||||
|
//If command is empty, DefaultCommand is used
|
||||||
|
Command string
|
||||||
|
Root string
|
||||||
|
Debug bool
|
||||||
|
Log string
|
||||||
|
LogFormat Format
|
||||||
|
PdeathSignal unix.Signal
|
||||||
|
Setpgid bool
|
||||||
|
Criu string
|
||||||
|
SystemdCgroup bool
|
||||||
|
Rootless *bool // nil stands for "auto"
|
||||||
|
}
|
31
vendor/github.com/containerd/go-runc/runc_windows.go
generated
vendored
Normal file
31
vendor/github.com/containerd/go-runc/runc_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package runc
|
||||||
|
|
||||||
|
// Runc is the client to the runc cli
|
||||||
|
type Runc struct {
|
||||||
|
//If command is empty, DefaultCommand is used
|
||||||
|
Command string
|
||||||
|
Root string
|
||||||
|
Debug bool
|
||||||
|
Log string
|
||||||
|
LogFormat Format
|
||||||
|
Setpgid bool
|
||||||
|
Criu string
|
||||||
|
SystemdCgroup bool
|
||||||
|
Rootless *bool // nil stands for "auto"
|
||||||
|
}
|
1
vendor/github.com/mitchellh/hashstructure/go.mod
generated
vendored
Normal file
1
vendor/github.com/mitchellh/hashstructure/go.mod
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
module github.com/mitchellh/hashstructure
|
20
vendor/github.com/moby/buildkit/README.md
generated
vendored
20
vendor/github.com/moby/buildkit/README.md
generated
vendored
|
@ -62,6 +62,7 @@ You don't need to read this document unless you want to use the full-featured st
|
||||||
- [Expose BuildKit as a TCP service](#expose-buildkit-as-a-tcp-service)
|
- [Expose BuildKit as a TCP service](#expose-buildkit-as-a-tcp-service)
|
||||||
- [Load balancing](#load-balancing)
|
- [Load balancing](#load-balancing)
|
||||||
- [Containerizing BuildKit](#containerizing-buildkit)
|
- [Containerizing BuildKit](#containerizing-buildkit)
|
||||||
|
- [Podman](#podman)
|
||||||
- [Kubernetes](#kubernetes)
|
- [Kubernetes](#kubernetes)
|
||||||
- [Daemonless](#daemonless)
|
- [Daemonless](#daemonless)
|
||||||
- [Opentracing support](#opentracing-support)
|
- [Opentracing support](#opentracing-support)
|
||||||
|
@ -127,11 +128,6 @@ We are open to adding more backends.
|
||||||
The buildkitd daemon listens gRPC API on `/run/buildkit/buildkitd.sock` by default, but you can also use TCP sockets.
|
The buildkitd daemon listens gRPC API on `/run/buildkit/buildkitd.sock` by default, but you can also use TCP sockets.
|
||||||
See [Expose BuildKit as a TCP service](#expose-buildkit-as-a-tcp-service).
|
See [Expose BuildKit as a TCP service](#expose-buildkit-as-a-tcp-service).
|
||||||
|
|
||||||
:information_source: Notice to Fedora 31 users:
|
|
||||||
|
|
||||||
* As runc still does not work on cgroup v2 environment like Fedora 31, you need to substitute runc with crun. Run `buildkitd` with `--oci-worker-binary=crun`.
|
|
||||||
* If you want to use runc, you need to configure the system to use cgroup v1. Run `sudo grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=0"` and reboot.
|
|
||||||
|
|
||||||
### Exploring LLB
|
### Exploring LLB
|
||||||
|
|
||||||
BuildKit builds are based on a binary intermediate format called LLB that is used for defining the dependency graph for processes running part of your build. tl;dr: LLB is to Dockerfile what LLVM IR is to C.
|
BuildKit builds are based on a binary intermediate format called LLB that is used for defining the dependency graph for processes running part of your build. tl;dr: LLB is to Dockerfile what LLVM IR is to C.
|
||||||
|
@ -150,6 +146,9 @@ Currently, the following high-level languages has been implemented for LLB:
|
||||||
- [Mockerfile](https://matt-rickard.com/building-a-new-dockerfile-frontend/)
|
- [Mockerfile](https://matt-rickard.com/building-a-new-dockerfile-frontend/)
|
||||||
- [Gockerfile](https://github.com/po3rin/gockerfile)
|
- [Gockerfile](https://github.com/po3rin/gockerfile)
|
||||||
- [bldr (Pkgfile)](https://github.com/talos-systems/bldr/)
|
- [bldr (Pkgfile)](https://github.com/talos-systems/bldr/)
|
||||||
|
- [HLB](https://github.com/openllb/hlb)
|
||||||
|
- [Earthfile (Earthly)](https://github.com/earthly/earthly)
|
||||||
|
- [Cargo Wharf (Rust)](https://github.com/denzp/cargo-wharf)
|
||||||
- (open a PR to add your own language)
|
- (open a PR to add your own language)
|
||||||
|
|
||||||
### Exploring Dockerfiles
|
### Exploring Dockerfiles
|
||||||
|
@ -353,6 +352,7 @@ The directory layout conforms to OCI Image Spec v1.0.
|
||||||
- `mode=max`: export all the layers of all intermediate steps. Not supported for `inline` cache exporter.
|
- `mode=max`: export all the layers of all intermediate steps. Not supported for `inline` cache exporter.
|
||||||
- `ref=docker.io/user/image:tag`: reference for `registry` cache exporter
|
- `ref=docker.io/user/image:tag`: reference for `registry` cache exporter
|
||||||
- `dest=path/to/output-dir`: directory for `local` cache exporter
|
- `dest=path/to/output-dir`: directory for `local` cache exporter
|
||||||
|
- `oci-mediatypes=true|false`: whether to use OCI mediatypes in exported manifests for `local` and `registry` exporter. Since BuildKit `v0.8` defaults to true.
|
||||||
|
|
||||||
#### `--import-cache` options
|
#### `--import-cache` options
|
||||||
- `type`: `registry` or `local`. Use `registry` to import `inline` cache.
|
- `type`: `registry` or `local`. Use `registry` to import `inline` cache.
|
||||||
|
@ -418,6 +418,16 @@ export BUILDKIT_HOST=docker-container://buildkitd
|
||||||
buildctl build --help
|
buildctl build --help
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Podman
|
||||||
|
To connect to a BuildKit daemon running in a Podman container, use `podman-container://` instead of `docker-container://` .
|
||||||
|
|
||||||
|
```bash
|
||||||
|
podman run -d --name buildkitd --privileged moby/buildkit:latest
|
||||||
|
buildctl --addr=podman-container://buildkitd build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=oci | podman load foo
|
||||||
|
```
|
||||||
|
|
||||||
|
`sudo` is not required.
|
||||||
|
|
||||||
### Kubernetes
|
### Kubernetes
|
||||||
|
|
||||||
For Kubernetes deployments, see [`examples/kubernetes`](./examples/kubernetes).
|
For Kubernetes deployments, see [`examples/kubernetes`](./examples/kubernetes).
|
||||||
|
|
2
vendor/github.com/moby/buildkit/api/services/control/generate.go
generated
vendored
2
vendor/github.com/moby/buildkit/api/services/control/generate.go
generated
vendored
|
@ -1,3 +1,3 @@
|
||||||
package moby_buildkit_v1
|
package moby_buildkit_v1 //nolint:golint
|
||||||
|
|
||||||
//go:generate protoc -I=. -I=../../../vendor/ -I=../../../../../../ --gogo_out=plugins=grpc:. control.proto
|
//go:generate protoc -I=. -I=../../../vendor/ -I=../../../../../../ --gogo_out=plugins=grpc:. control.proto
|
||||||
|
|
2
vendor/github.com/moby/buildkit/api/types/generate.go
generated
vendored
2
vendor/github.com/moby/buildkit/api/types/generate.go
generated
vendored
|
@ -1,3 +1,3 @@
|
||||||
package moby_buildkit_v1_types
|
package moby_buildkit_v1_types //nolint:golint
|
||||||
|
|
||||||
//go:generate protoc -I=. -I=../../vendor/ -I=../../../../../ --gogo_out=plugins=grpc:. worker.proto
|
//go:generate protoc -I=. -I=../../vendor/ -I=../../../../../ --gogo_out=plugins=grpc:. worker.proto
|
||||||
|
|
236
vendor/github.com/moby/buildkit/cache/blobs.go
generated
vendored
Normal file
236
vendor/github.com/moby/buildkit/cache/blobs.go
generated
vendored
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/diff"
|
||||||
|
"github.com/containerd/containerd/leases"
|
||||||
|
"github.com/containerd/containerd/mount"
|
||||||
|
"github.com/moby/buildkit/session"
|
||||||
|
"github.com/moby/buildkit/util/compression"
|
||||||
|
"github.com/moby/buildkit/util/flightcontrol"
|
||||||
|
"github.com/moby/buildkit/util/winlayers"
|
||||||
|
digest "github.com/opencontainers/go-digest"
|
||||||
|
imagespecidentity "github.com/opencontainers/image-spec/identity"
|
||||||
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
|
var g flightcontrol.Group
|
||||||
|
|
||||||
|
const containerdUncompressed = "containerd.io/uncompressed"
|
||||||
|
|
||||||
|
type CompareWithParent interface {
|
||||||
|
CompareWithParent(ctx context.Context, ref string, opts ...diff.Opt) (ocispec.Descriptor, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ErrNoBlobs = errors.Errorf("no blobs for snapshot")
|
||||||
|
|
||||||
|
// computeBlobChain ensures every ref in a parent chain has an associated blob in the content store. If
|
||||||
|
// a blob is missing and createIfNeeded is true, then the blob will be created, otherwise ErrNoBlobs will
|
||||||
|
// be returned. Caller must hold a lease when calling this function.
|
||||||
|
func (sr *immutableRef) computeBlobChain(ctx context.Context, createIfNeeded bool, compressionType compression.Type, s session.Group) error {
|
||||||
|
if _, ok := leases.FromContext(ctx); !ok {
|
||||||
|
return errors.Errorf("missing lease requirement for computeBlobChain")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := sr.Finalize(ctx, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if isTypeWindows(sr) {
|
||||||
|
ctx = winlayers.UseWindowsLayerMode(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return computeBlobChain(ctx, sr, createIfNeeded, compressionType, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func computeBlobChain(ctx context.Context, sr *immutableRef, createIfNeeded bool, compressionType compression.Type, s session.Group) error {
|
||||||
|
baseCtx := ctx
|
||||||
|
eg, ctx := errgroup.WithContext(ctx)
|
||||||
|
var currentDescr ocispec.Descriptor
|
||||||
|
if sr.parent != nil {
|
||||||
|
eg.Go(func() error {
|
||||||
|
return computeBlobChain(ctx, sr.parent, createIfNeeded, compressionType, s)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
eg.Go(func() error {
|
||||||
|
dp, err := g.Do(ctx, sr.ID(), func(ctx context.Context) (interface{}, error) {
|
||||||
|
refInfo := sr.Info()
|
||||||
|
if refInfo.Blob != "" {
|
||||||
|
return nil, nil
|
||||||
|
} else if !createIfNeeded {
|
||||||
|
return nil, errors.WithStack(ErrNoBlobs)
|
||||||
|
}
|
||||||
|
|
||||||
|
var mediaType string
|
||||||
|
switch compressionType {
|
||||||
|
case compression.Uncompressed:
|
||||||
|
mediaType = ocispec.MediaTypeImageLayer
|
||||||
|
case compression.Gzip:
|
||||||
|
mediaType = ocispec.MediaTypeImageLayerGzip
|
||||||
|
default:
|
||||||
|
return nil, errors.Errorf("unknown layer compression type: %q", compressionType)
|
||||||
|
}
|
||||||
|
|
||||||
|
var descr ocispec.Descriptor
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if pc, ok := sr.cm.Differ.(CompareWithParent); ok {
|
||||||
|
descr, err = pc.CompareWithParent(ctx, sr.ID(), diff.WithMediaType(mediaType))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if descr.Digest == "" {
|
||||||
|
// reference needs to be committed
|
||||||
|
var lower []mount.Mount
|
||||||
|
if sr.parent != nil {
|
||||||
|
m, err := sr.parent.Mount(ctx, true, s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var release func() error
|
||||||
|
lower, release, err = m.Mount()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if release != nil {
|
||||||
|
defer release()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m, err := sr.Mount(ctx, true, s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
upper, release, err := m.Mount()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if release != nil {
|
||||||
|
defer release()
|
||||||
|
}
|
||||||
|
descr, err = sr.cm.Differ.Compare(ctx, lower, upper,
|
||||||
|
diff.WithMediaType(mediaType),
|
||||||
|
diff.WithReference(sr.ID()),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if descr.Annotations == nil {
|
||||||
|
descr.Annotations = map[string]string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := sr.cm.ContentStore.Info(ctx, descr.Digest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if diffID, ok := info.Labels[containerdUncompressed]; ok {
|
||||||
|
descr.Annotations[containerdUncompressed] = diffID
|
||||||
|
} else if compressionType == compression.Uncompressed {
|
||||||
|
descr.Annotations[containerdUncompressed] = descr.Digest.String()
|
||||||
|
} else {
|
||||||
|
return nil, errors.Errorf("unknown layer compression type")
|
||||||
|
}
|
||||||
|
|
||||||
|
return descr, nil
|
||||||
|
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if dp != nil {
|
||||||
|
currentDescr = dp.(ocispec.Descriptor)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
err := eg.Wait()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if currentDescr.Digest != "" {
|
||||||
|
if err := sr.setBlob(baseCtx, currentDescr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// setBlob associates a blob with the cache record.
|
||||||
|
// A lease must be held for the blob when calling this function
|
||||||
|
// Caller should call Info() for knowing what current values are actually set
|
||||||
|
func (sr *immutableRef) setBlob(ctx context.Context, desc ocispec.Descriptor) error {
|
||||||
|
if _, ok := leases.FromContext(ctx); !ok {
|
||||||
|
return errors.Errorf("missing lease requirement for setBlob")
|
||||||
|
}
|
||||||
|
|
||||||
|
diffID, err := diffIDFromDescriptor(desc)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := sr.cm.ContentStore.Info(ctx, desc.Digest); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sr.mu.Lock()
|
||||||
|
defer sr.mu.Unlock()
|
||||||
|
|
||||||
|
if getChainID(sr.md) != "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := sr.finalize(ctx, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p := sr.parent
|
||||||
|
var parentChainID digest.Digest
|
||||||
|
var parentBlobChainID digest.Digest
|
||||||
|
if p != nil {
|
||||||
|
pInfo := p.Info()
|
||||||
|
if pInfo.ChainID == "" || pInfo.BlobChainID == "" {
|
||||||
|
return errors.Errorf("failed to set blob for reference with non-addressable parent")
|
||||||
|
}
|
||||||
|
parentChainID = pInfo.ChainID
|
||||||
|
parentBlobChainID = pInfo.BlobChainID
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := sr.cm.LeaseManager.AddResource(ctx, leases.Lease{ID: sr.ID()}, leases.Resource{
|
||||||
|
ID: desc.Digest.String(),
|
||||||
|
Type: "content",
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
queueDiffID(sr.md, diffID.String())
|
||||||
|
queueBlob(sr.md, desc.Digest.String())
|
||||||
|
chainID := diffID
|
||||||
|
blobChainID := imagespecidentity.ChainID([]digest.Digest{desc.Digest, diffID})
|
||||||
|
if parentChainID != "" {
|
||||||
|
chainID = imagespecidentity.ChainID([]digest.Digest{parentChainID, chainID})
|
||||||
|
blobChainID = imagespecidentity.ChainID([]digest.Digest{parentBlobChainID, blobChainID})
|
||||||
|
}
|
||||||
|
queueChainID(sr.md, chainID.String())
|
||||||
|
queueBlobChainID(sr.md, blobChainID.String())
|
||||||
|
queueMediaType(sr.md, desc.MediaType)
|
||||||
|
queueBlobSize(sr.md, desc.Size)
|
||||||
|
if err := sr.md.Commit(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isTypeWindows(sr *immutableRef) bool {
|
||||||
|
if GetLayerType(sr) == "windows" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if parent := sr.parent; parent != nil {
|
||||||
|
return isTypeWindows(parent)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
54
vendor/github.com/moby/buildkit/cache/contenthash/checksum.go
generated
vendored
54
vendor/github.com/moby/buildkit/cache/contenthash/checksum.go
generated
vendored
|
@ -11,12 +11,13 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
"github.com/docker/docker/pkg/locker"
|
|
||||||
iradix "github.com/hashicorp/go-immutable-radix"
|
iradix "github.com/hashicorp/go-immutable-radix"
|
||||||
"github.com/hashicorp/golang-lru/simplelru"
|
"github.com/hashicorp/golang-lru/simplelru"
|
||||||
"github.com/moby/buildkit/cache"
|
"github.com/moby/buildkit/cache"
|
||||||
"github.com/moby/buildkit/cache/metadata"
|
"github.com/moby/buildkit/cache/metadata"
|
||||||
|
"github.com/moby/buildkit/session"
|
||||||
"github.com/moby/buildkit/snapshot"
|
"github.com/moby/buildkit/snapshot"
|
||||||
|
"github.com/moby/locker"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/tonistiigi/fsutil"
|
"github.com/tonistiigi/fsutil"
|
||||||
|
@ -44,12 +45,12 @@ func getDefaultManager() *cacheManager {
|
||||||
// header, "/dir" is for contents. For the root node "" (empty string) is the
|
// header, "/dir" is for contents. For the root node "" (empty string) is the
|
||||||
// key for root, "/" for the root header
|
// key for root, "/" for the root header
|
||||||
|
|
||||||
func Checksum(ctx context.Context, ref cache.ImmutableRef, path string, followLinks bool) (digest.Digest, error) {
|
func Checksum(ctx context.Context, ref cache.ImmutableRef, path string, followLinks bool, s session.Group) (digest.Digest, error) {
|
||||||
return getDefaultManager().Checksum(ctx, ref, path, followLinks)
|
return getDefaultManager().Checksum(ctx, ref, path, followLinks, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ChecksumWildcard(ctx context.Context, ref cache.ImmutableRef, path string, followLinks bool) (digest.Digest, error) {
|
func ChecksumWildcard(ctx context.Context, ref cache.ImmutableRef, path string, followLinks bool, s session.Group) (digest.Digest, error) {
|
||||||
return getDefaultManager().ChecksumWildcard(ctx, ref, path, followLinks)
|
return getDefaultManager().ChecksumWildcard(ctx, ref, path, followLinks, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCacheContext(ctx context.Context, md *metadata.StorageItem, idmap *idtools.IdentityMapping) (CacheContext, error) {
|
func GetCacheContext(ctx context.Context, md *metadata.StorageItem, idmap *idtools.IdentityMapping) (CacheContext, error) {
|
||||||
|
@ -65,8 +66,8 @@ func ClearCacheContext(md *metadata.StorageItem) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type CacheContext interface {
|
type CacheContext interface {
|
||||||
Checksum(ctx context.Context, ref cache.Mountable, p string, followLinks bool) (digest.Digest, error)
|
Checksum(ctx context.Context, ref cache.Mountable, p string, followLinks bool, s session.Group) (digest.Digest, error)
|
||||||
ChecksumWildcard(ctx context.Context, ref cache.Mountable, p string, followLinks bool) (digest.Digest, error)
|
ChecksumWildcard(ctx context.Context, ref cache.Mountable, p string, followLinks bool, s session.Group) (digest.Digest, error)
|
||||||
HandleChange(kind fsutil.ChangeKind, p string, fi os.FileInfo, err error) error
|
HandleChange(kind fsutil.ChangeKind, p string, fi os.FileInfo, err error) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,20 +86,20 @@ type cacheManager struct {
|
||||||
lruMu sync.Mutex
|
lruMu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cm *cacheManager) Checksum(ctx context.Context, ref cache.ImmutableRef, p string, followLinks bool) (digest.Digest, error) {
|
func (cm *cacheManager) Checksum(ctx context.Context, ref cache.ImmutableRef, p string, followLinks bool, s session.Group) (digest.Digest, error) {
|
||||||
cc, err := cm.GetCacheContext(ctx, ensureOriginMetadata(ref.Metadata()), ref.IdentityMapping())
|
cc, err := cm.GetCacheContext(ctx, ensureOriginMetadata(ref.Metadata()), ref.IdentityMapping())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
return cc.Checksum(ctx, ref, p, followLinks)
|
return cc.Checksum(ctx, ref, p, followLinks, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cm *cacheManager) ChecksumWildcard(ctx context.Context, ref cache.ImmutableRef, p string, followLinks bool) (digest.Digest, error) {
|
func (cm *cacheManager) ChecksumWildcard(ctx context.Context, ref cache.ImmutableRef, p string, followLinks bool, s session.Group) (digest.Digest, error) {
|
||||||
cc, err := cm.GetCacheContext(ctx, ensureOriginMetadata(ref.Metadata()), ref.IdentityMapping())
|
cc, err := cm.GetCacheContext(ctx, ensureOriginMetadata(ref.Metadata()), ref.IdentityMapping())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
return cc.ChecksumWildcard(ctx, ref, p, followLinks)
|
return cc.ChecksumWildcard(ctx, ref, p, followLinks, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cm *cacheManager) GetCacheContext(ctx context.Context, md *metadata.StorageItem, idmap *idtools.IdentityMapping) (CacheContext, error) {
|
func (cm *cacheManager) GetCacheContext(ctx context.Context, md *metadata.StorageItem, idmap *idtools.IdentityMapping) (CacheContext, error) {
|
||||||
|
@ -170,13 +171,14 @@ type mount struct {
|
||||||
mountable cache.Mountable
|
mountable cache.Mountable
|
||||||
mountPath string
|
mountPath string
|
||||||
unmount func() error
|
unmount func() error
|
||||||
|
session session.Group
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mount) mount(ctx context.Context) (string, error) {
|
func (m *mount) mount(ctx context.Context) (string, error) {
|
||||||
if m.mountPath != "" {
|
if m.mountPath != "" {
|
||||||
return m.mountPath, nil
|
return m.mountPath, nil
|
||||||
}
|
}
|
||||||
mounts, err := m.mountable.Mount(ctx, true)
|
mounts, err := m.mountable.Mount(ctx, true, m.session)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -380,13 +382,13 @@ func (cc *cacheContext) HandleChange(kind fsutil.ChangeKind, p string, fi os.Fil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cc *cacheContext) ChecksumWildcard(ctx context.Context, mountable cache.Mountable, p string, followLinks bool) (digest.Digest, error) {
|
func (cc *cacheContext) ChecksumWildcard(ctx context.Context, mountable cache.Mountable, p string, followLinks bool, s session.Group) (digest.Digest, error) {
|
||||||
m := &mount{mountable: mountable}
|
m := &mount{mountable: mountable, session: s}
|
||||||
defer m.clean()
|
defer m.clean()
|
||||||
|
|
||||||
wildcards, err := cc.wildcards(ctx, m, p)
|
wildcards, err := cc.wildcards(ctx, m, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if followLinks {
|
if followLinks {
|
||||||
|
@ -413,13 +415,12 @@ func (cc *cacheContext) ChecksumWildcard(ctx context.Context, mountable cache.Mo
|
||||||
digester.Hash().Write([]byte(w.Record.Digest))
|
digester.Hash().Write([]byte(w.Record.Digest))
|
||||||
}
|
}
|
||||||
return digester.Digest(), nil
|
return digester.Digest(), nil
|
||||||
} else {
|
|
||||||
return wildcards[0].Record.Digest, nil
|
|
||||||
}
|
}
|
||||||
|
return wildcards[0].Record.Digest, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable, p string, followLinks bool) (digest.Digest, error) {
|
func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable, p string, followLinks bool, s session.Group) (digest.Digest, error) {
|
||||||
m := &mount{mountable: mountable}
|
m := &mount{mountable: mountable, session: s}
|
||||||
defer m.clean()
|
defer m.clean()
|
||||||
|
|
||||||
return cc.checksumFollow(ctx, m, p, followLinks)
|
return cc.checksumFollow(ctx, m, p, followLinks)
|
||||||
|
@ -688,12 +689,13 @@ func (cc *cacheContext) needsScanFollow(root *iradix.Node, p string, linksWalked
|
||||||
if p == "/" {
|
if p == "/" {
|
||||||
p = ""
|
p = ""
|
||||||
}
|
}
|
||||||
if v, ok := root.Get(convertPathToKey([]byte(p))); !ok {
|
v, ok := root.Get(convertPathToKey([]byte(p)))
|
||||||
|
if !ok {
|
||||||
if p == "" {
|
if p == "" {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
return cc.needsScanFollow(root, path.Clean(path.Dir(p)), linksWalked)
|
return cc.needsScanFollow(root, path.Clean(path.Dir(p)), linksWalked)
|
||||||
} else {
|
}
|
||||||
cr := v.(*CacheRecord)
|
cr := v.(*CacheRecord)
|
||||||
if cr.Type == CacheRecordTypeSymlink {
|
if cr.Type == CacheRecordTypeSymlink {
|
||||||
if *linksWalked > 255 {
|
if *linksWalked > 255 {
|
||||||
|
@ -706,7 +708,6 @@ func (cc *cacheContext) needsScanFollow(root *iradix.Node, p string, linksWalked
|
||||||
}
|
}
|
||||||
return cc.needsScanFollow(root, link, linksWalked)
|
return cc.needsScanFollow(root, link, linksWalked)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -875,12 +876,15 @@ func ensureOriginMetadata(md *metadata.StorageItem) *metadata.StorageItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
var pool32K = sync.Pool{
|
var pool32K = sync.Pool{
|
||||||
New: func() interface{} { return make([]byte, 32*1024) }, // 32K
|
New: func() interface{} {
|
||||||
|
buf := make([]byte, 32*1024) // 32K
|
||||||
|
return &buf
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func poolsCopy(dst io.Writer, src io.Reader) (written int64, err error) {
|
func poolsCopy(dst io.Writer, src io.Reader) (written int64, err error) {
|
||||||
buf := pool32K.Get().([]byte)
|
buf := pool32K.Get().(*[]byte)
|
||||||
written, err = io.CopyBuffer(dst, src, buf)
|
written, err = io.CopyBuffer(dst, src, *buf)
|
||||||
pool32K.Put(buf)
|
pool32K.Put(buf)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
8
vendor/github.com/moby/buildkit/cache/contenthash/filehash.go
generated
vendored
8
vendor/github.com/moby/buildkit/cache/contenthash/filehash.go
generated
vendored
|
@ -40,20 +40,22 @@ func NewFileHash(path string, fi os.FileInfo) (hash.Hash, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFromStat(stat *fstypes.Stat) (hash.Hash, error) {
|
func NewFromStat(stat *fstypes.Stat) (hash.Hash, error) {
|
||||||
|
// Clear the socket bit since archive/tar.FileInfoHeader does not handle it
|
||||||
|
stat.Mode &^= uint32(os.ModeSocket)
|
||||||
|
|
||||||
fi := &statInfo{stat}
|
fi := &statInfo{stat}
|
||||||
hdr, err := tar.FileInfoHeader(fi, stat.Linkname)
|
hdr, err := tar.FileInfoHeader(fi, stat.Linkname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
hdr.Name = "" // note: empty name is different from current has in docker build. Name is added on recursive directory scan instead
|
hdr.Name = "" // note: empty name is different from current has in docker build. Name is added on recursive directory scan instead
|
||||||
hdr.Mode = int64(chmodWindowsTarEntry(os.FileMode(hdr.Mode)))
|
|
||||||
hdr.Devmajor = stat.Devmajor
|
hdr.Devmajor = stat.Devmajor
|
||||||
hdr.Devminor = stat.Devminor
|
hdr.Devminor = stat.Devminor
|
||||||
|
|
||||||
if len(stat.Xattrs) > 0 {
|
if len(stat.Xattrs) > 0 {
|
||||||
hdr.Xattrs = make(map[string]string, len(stat.Xattrs))
|
hdr.PAXRecords = make(map[string]string, len(stat.Xattrs))
|
||||||
for k, v := range stat.Xattrs {
|
for k, v := range stat.Xattrs {
|
||||||
hdr.Xattrs[k] = string(v)
|
hdr.PAXRecords["SCHILY.xattr."+k] = string(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fmt.Printf("hdr: %#v\n", hdr)
|
// fmt.Printf("hdr: %#v\n", hdr)
|
||||||
|
|
4
vendor/github.com/moby/buildkit/cache/contenthash/filehash_unix.go
generated
vendored
4
vendor/github.com/moby/buildkit/cache/contenthash/filehash_unix.go
generated
vendored
|
@ -12,10 +12,6 @@ import (
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
func chmodWindowsTarEntry(perm os.FileMode) os.FileMode {
|
|
||||||
return perm
|
|
||||||
}
|
|
||||||
|
|
||||||
func setUnixOpt(path string, fi os.FileInfo, stat *fstypes.Stat) error {
|
func setUnixOpt(path string, fi os.FileInfo, stat *fstypes.Stat) error {
|
||||||
s := fi.Sys().(*syscall.Stat_t)
|
s := fi.Sys().(*syscall.Stat_t)
|
||||||
|
|
||||||
|
|
10
vendor/github.com/moby/buildkit/cache/contenthash/filehash_windows.go
generated
vendored
10
vendor/github.com/moby/buildkit/cache/contenthash/filehash_windows.go
generated
vendored
|
@ -8,16 +8,6 @@ import (
|
||||||
fstypes "github.com/tonistiigi/fsutil/types"
|
fstypes "github.com/tonistiigi/fsutil/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// chmodWindowsTarEntry is used to adjust the file permissions used in tar
|
|
||||||
// header based on the platform the archival is done.
|
|
||||||
func chmodWindowsTarEntry(perm os.FileMode) os.FileMode {
|
|
||||||
perm &= 0755
|
|
||||||
// Add the x bit: make everything +x from windows
|
|
||||||
perm |= 0111
|
|
||||||
|
|
||||||
return perm
|
|
||||||
}
|
|
||||||
|
|
||||||
func setUnixOpt(path string, fi os.FileInfo, stat *fstypes.Stat) error {
|
func setUnixOpt(path string, fi os.FileInfo, stat *fstypes.Stat) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
19
vendor/github.com/moby/buildkit/cache/contenthash/tarsum.go
generated
vendored
19
vendor/github.com/moby/buildkit/cache/contenthash/tarsum.go
generated
vendored
|
@ -36,13 +36,26 @@ func v0TarHeaderSelect(h *tar.Header) (orderedHeaders [][2]string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func v1TarHeaderSelect(h *tar.Header) (orderedHeaders [][2]string) {
|
func v1TarHeaderSelect(h *tar.Header) (orderedHeaders [][2]string) {
|
||||||
|
pax := h.PAXRecords
|
||||||
|
if len(h.Xattrs) > 0 { //nolint deprecated
|
||||||
|
if pax == nil {
|
||||||
|
pax = map[string]string{}
|
||||||
|
for k, v := range h.Xattrs { //nolint deprecated
|
||||||
|
pax["SCHILY.xattr."+k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get extended attributes.
|
// Get extended attributes.
|
||||||
xAttrKeys := make([]string, len(h.Xattrs))
|
xAttrKeys := make([]string, len(h.PAXRecords))
|
||||||
for k := range h.Xattrs {
|
for k := range pax {
|
||||||
|
if strings.HasPrefix(k, "SCHILY.xattr.") {
|
||||||
|
k = strings.TrimPrefix(k, "SCHILY.xattr.")
|
||||||
if k == "security.capability" || !strings.HasPrefix(k, "security.") && !strings.HasPrefix(k, "system.") {
|
if k == "security.capability" || !strings.HasPrefix(k, "security.") && !strings.HasPrefix(k, "system.") {
|
||||||
xAttrKeys = append(xAttrKeys, k)
|
xAttrKeys = append(xAttrKeys, k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
sort.Strings(xAttrKeys)
|
sort.Strings(xAttrKeys)
|
||||||
|
|
||||||
// Make the slice with enough capacity to hold the 11 basic headers
|
// Make the slice with enough capacity to hold the 11 basic headers
|
||||||
|
@ -56,7 +69,7 @@ func v1TarHeaderSelect(h *tar.Header) (orderedHeaders [][2]string) {
|
||||||
|
|
||||||
// Finally, append the sorted xattrs.
|
// Finally, append the sorted xattrs.
|
||||||
for _, k := range xAttrKeys {
|
for _, k := range xAttrKeys {
|
||||||
orderedHeaders = append(orderedHeaders, [2]string{k, h.Xattrs[k]})
|
orderedHeaders = append(orderedHeaders, [2]string{k, h.PAXRecords["SCHILY.xattr."+k]})
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
156
vendor/github.com/moby/buildkit/cache/manager.go
generated
vendored
156
vendor/github.com/moby/buildkit/cache/manager.go
generated
vendored
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
"github.com/containerd/containerd/diff"
|
"github.com/containerd/containerd/diff"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/filters"
|
"github.com/containerd/containerd/filters"
|
||||||
"github.com/containerd/containerd/gc"
|
"github.com/containerd/containerd/gc"
|
||||||
"github.com/containerd/containerd/leases"
|
"github.com/containerd/containerd/leases"
|
||||||
|
@ -15,7 +16,9 @@ import (
|
||||||
"github.com/moby/buildkit/cache/metadata"
|
"github.com/moby/buildkit/cache/metadata"
|
||||||
"github.com/moby/buildkit/client"
|
"github.com/moby/buildkit/client"
|
||||||
"github.com/moby/buildkit/identity"
|
"github.com/moby/buildkit/identity"
|
||||||
|
"github.com/moby/buildkit/session"
|
||||||
"github.com/moby/buildkit/snapshot"
|
"github.com/moby/buildkit/snapshot"
|
||||||
|
"github.com/moby/buildkit/util/flightcontrol"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
imagespecidentity "github.com/opencontainers/image-spec/identity"
|
imagespecidentity "github.com/opencontainers/image-spec/identity"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
@ -38,14 +41,15 @@ type ManagerOpt struct {
|
||||||
PruneRefChecker ExternalRefCheckerFunc
|
PruneRefChecker ExternalRefCheckerFunc
|
||||||
GarbageCollect func(ctx context.Context) (gc.Stats, error)
|
GarbageCollect func(ctx context.Context) (gc.Stats, error)
|
||||||
Applier diff.Applier
|
Applier diff.Applier
|
||||||
|
Differ diff.Comparer
|
||||||
}
|
}
|
||||||
|
|
||||||
type Accessor interface {
|
type Accessor interface {
|
||||||
GetByBlob(ctx context.Context, desc ocispec.Descriptor, parent ImmutableRef, opts ...RefOption) (ImmutableRef, error)
|
GetByBlob(ctx context.Context, desc ocispec.Descriptor, parent ImmutableRef, opts ...RefOption) (ImmutableRef, error)
|
||||||
Get(ctx context.Context, id string, opts ...RefOption) (ImmutableRef, error)
|
Get(ctx context.Context, id string, opts ...RefOption) (ImmutableRef, error)
|
||||||
|
|
||||||
New(ctx context.Context, parent ImmutableRef, opts ...RefOption) (MutableRef, error)
|
New(ctx context.Context, parent ImmutableRef, s session.Group, opts ...RefOption) (MutableRef, error)
|
||||||
GetMutable(ctx context.Context, id string) (MutableRef, error) // Rebase?
|
GetMutable(ctx context.Context, id string, opts ...RefOption) (MutableRef, error) // Rebase?
|
||||||
IdentityMapping() *idtools.IdentityMapping
|
IdentityMapping() *idtools.IdentityMapping
|
||||||
Metadata(string) *metadata.StorageItem
|
Metadata(string) *metadata.StorageItem
|
||||||
}
|
}
|
||||||
|
@ -74,6 +78,7 @@ type cacheManager struct {
|
||||||
md *metadata.Store
|
md *metadata.Store
|
||||||
|
|
||||||
muPrune sync.Mutex // make sure parallel prune is not allowed so there will not be inconsistent results
|
muPrune sync.Mutex // make sure parallel prune is not allowed so there will not be inconsistent results
|
||||||
|
unlazyG flightcontrol.Group
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewManager(opt ManagerOpt) (Manager, error) {
|
func NewManager(opt ManagerOpt) (Manager, error) {
|
||||||
|
@ -92,7 +97,7 @@ func NewManager(opt ManagerOpt) (Manager, error) {
|
||||||
return cm, nil
|
return cm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor, parent ImmutableRef, opts ...RefOption) (ir ImmutableRef, err error) {
|
func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor, parent ImmutableRef, opts ...RefOption) (ir ImmutableRef, rerr error) {
|
||||||
diffID, err := diffIDFromDescriptor(desc)
|
diffID, err := diffIDFromDescriptor(desc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -100,9 +105,12 @@ func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor,
|
||||||
chainID := diffID
|
chainID := diffID
|
||||||
blobChainID := imagespecidentity.ChainID([]digest.Digest{desc.Digest, diffID})
|
blobChainID := imagespecidentity.ChainID([]digest.Digest{desc.Digest, diffID})
|
||||||
|
|
||||||
if desc.Digest != "" {
|
descHandlers := descHandlersOf(opts...)
|
||||||
if _, err := cm.ContentStore.Info(ctx, desc.Digest); err != nil {
|
if desc.Digest != "" && (descHandlers == nil || descHandlers[desc.Digest] == nil) {
|
||||||
return nil, errors.Wrapf(err, "failed to get blob %s", desc.Digest)
|
if _, err := cm.ContentStore.Info(ctx, desc.Digest); errors.Is(err, errdefs.ErrNotFound) {
|
||||||
|
return nil, NeedsRemoteProvidersError([]digest.Digest{desc.Digest})
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +123,8 @@ func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor,
|
||||||
}
|
}
|
||||||
chainID = imagespecidentity.ChainID([]digest.Digest{pInfo.ChainID, chainID})
|
chainID = imagespecidentity.ChainID([]digest.Digest{pInfo.ChainID, chainID})
|
||||||
blobChainID = imagespecidentity.ChainID([]digest.Digest{pInfo.BlobChainID, blobChainID})
|
blobChainID = imagespecidentity.ChainID([]digest.Digest{pInfo.BlobChainID, blobChainID})
|
||||||
p2, err := cm.Get(ctx, parent.ID(), NoUpdateLastUsed)
|
|
||||||
|
p2, err := cm.Get(ctx, parent.ID(), NoUpdateLastUsed, descHandlers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -128,7 +137,7 @@ func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor,
|
||||||
|
|
||||||
releaseParent := false
|
releaseParent := false
|
||||||
defer func() {
|
defer func() {
|
||||||
if releaseParent || err != nil && p != nil {
|
if releaseParent || rerr != nil && p != nil {
|
||||||
p.Release(context.TODO())
|
p.Release(context.TODO())
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -141,14 +150,17 @@ func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor,
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, si := range sis {
|
if len(sis) > 0 {
|
||||||
ref, err := cm.get(ctx, si.ID(), opts...)
|
ref, err := cm.get(ctx, sis[0].ID(), opts...)
|
||||||
if err != nil && !IsNotFound(err) {
|
if err != nil && !IsNotFound(err) {
|
||||||
return nil, errors.Wrapf(err, "failed to get record %s by blobchainid", si.ID())
|
return nil, errors.Wrapf(err, "failed to get record %s by blobchainid", sis[0].ID())
|
||||||
}
|
}
|
||||||
if p != nil {
|
if p != nil {
|
||||||
releaseParent = true
|
releaseParent = true
|
||||||
}
|
}
|
||||||
|
if err := setImageRefMetadata(ref, opts...); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to append image ref metadata to ref %s", ref.ID())
|
||||||
|
}
|
||||||
return ref, nil
|
return ref, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,13 +170,12 @@ func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor,
|
||||||
}
|
}
|
||||||
|
|
||||||
var link ImmutableRef
|
var link ImmutableRef
|
||||||
for _, si := range sis {
|
if len(sis) > 0 {
|
||||||
ref, err := cm.get(ctx, si.ID(), opts...)
|
ref, err := cm.get(ctx, sis[0].ID(), opts...)
|
||||||
if err != nil && !IsNotFound(err) {
|
if err != nil && !IsNotFound(err) {
|
||||||
return nil, errors.Wrapf(err, "failed to get record %s by chainid", si.ID())
|
return nil, errors.Wrapf(err, "failed to get record %s by chainid", sis[0].ID())
|
||||||
}
|
}
|
||||||
link = ref
|
link = ref
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
id := identity.NewID()
|
id := identity.NewID()
|
||||||
|
@ -188,7 +199,7 @@ func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor,
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if rerr != nil {
|
||||||
if err := cm.ManagerOpt.LeaseManager.Delete(context.TODO(), leases.Lease{
|
if err := cm.ManagerOpt.LeaseManager.Delete(context.TODO(), leases.Lease{
|
||||||
ID: l.ID,
|
ID: l.ID,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
@ -227,6 +238,10 @@ func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor,
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := setImageRefMetadata(rec, opts...); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to append image ref metadata to ref %s", rec.ID())
|
||||||
|
}
|
||||||
|
|
||||||
queueDiffID(rec.md, diffID.String())
|
queueDiffID(rec.md, diffID.String())
|
||||||
queueBlob(rec.md, desc.Digest.String())
|
queueBlob(rec.md, desc.Digest.String())
|
||||||
queueChainID(rec.md, chainID.String())
|
queueChainID(rec.md, chainID.String())
|
||||||
|
@ -234,6 +249,7 @@ func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor,
|
||||||
queueSnapshotID(rec.md, snapshotID)
|
queueSnapshotID(rec.md, snapshotID)
|
||||||
queueBlobOnly(rec.md, blobOnly)
|
queueBlobOnly(rec.md, blobOnly)
|
||||||
queueMediaType(rec.md, desc.MediaType)
|
queueMediaType(rec.md, desc.MediaType)
|
||||||
|
queueBlobSize(rec.md, desc.Size)
|
||||||
queueCommitted(rec.md)
|
queueCommitted(rec.md)
|
||||||
|
|
||||||
if err := rec.md.Commit(); err != nil {
|
if err := rec.md.Commit(); err != nil {
|
||||||
|
@ -242,7 +258,7 @@ func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor,
|
||||||
|
|
||||||
cm.records[id] = rec
|
cm.records[id] = rec
|
||||||
|
|
||||||
return rec.ref(true), nil
|
return rec.ref(true, descHandlers), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// init loads all snapshots from metadata state and tries to load the records
|
// init loads all snapshots from metadata state and tries to load the records
|
||||||
|
@ -308,25 +324,52 @@ func (cm *cacheManager) get(ctx context.Context, id string, opts ...RefOption) (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
descHandlers := descHandlersOf(opts...)
|
||||||
|
|
||||||
if rec.mutable {
|
if rec.mutable {
|
||||||
if len(rec.refs) != 0 {
|
if len(rec.refs) != 0 {
|
||||||
return nil, errors.Wrapf(ErrLocked, "%s is locked", id)
|
return nil, errors.Wrapf(ErrLocked, "%s is locked", id)
|
||||||
}
|
}
|
||||||
if rec.equalImmutable != nil {
|
if rec.equalImmutable != nil {
|
||||||
return rec.equalImmutable.ref(triggerUpdate), nil
|
return rec.equalImmutable.ref(triggerUpdate, descHandlers), nil
|
||||||
}
|
}
|
||||||
return rec.mref(triggerUpdate).commit(ctx)
|
return rec.mref(triggerUpdate, descHandlers).commit(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return rec.ref(triggerUpdate), nil
|
return rec.ref(triggerUpdate, descHandlers), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRecord returns record for id. Requires manager lock.
|
// getRecord returns record for id. Requires manager lock.
|
||||||
func (cm *cacheManager) getRecord(ctx context.Context, id string, opts ...RefOption) (cr *cacheRecord, retErr error) {
|
func (cm *cacheManager) getRecord(ctx context.Context, id string, opts ...RefOption) (cr *cacheRecord, retErr error) {
|
||||||
|
checkLazyProviders := func(rec *cacheRecord) error {
|
||||||
|
missing := NeedsRemoteProvidersError(nil)
|
||||||
|
dhs := descHandlersOf(opts...)
|
||||||
|
for {
|
||||||
|
blob := digest.Digest(getBlob(rec.md))
|
||||||
|
if isLazy, err := rec.isLazy(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
} else if isLazy && dhs[blob] == nil {
|
||||||
|
missing = append(missing, blob)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rec.parent == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
rec = rec.parent.cacheRecord
|
||||||
|
}
|
||||||
|
if len(missing) > 0 {
|
||||||
|
return missing
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if rec, ok := cm.records[id]; ok {
|
if rec, ok := cm.records[id]; ok {
|
||||||
if rec.isDead() {
|
if rec.isDead() {
|
||||||
return nil, errors.Wrapf(errNotFound, "failed to get dead record %s", id)
|
return nil, errors.Wrapf(errNotFound, "failed to get dead record %s", id)
|
||||||
}
|
}
|
||||||
|
if err := checkLazyProviders(rec); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return rec, nil
|
return rec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,11 +386,17 @@ func (cm *cacheManager) getRecord(ctx context.Context, id string, opts ...RefOpt
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parent refs are possibly lazy so keep it hold the description handlers.
|
||||||
|
var dhs DescHandlers
|
||||||
|
if mutable.parent != nil {
|
||||||
|
dhs = mutable.parent.descHandlers
|
||||||
|
}
|
||||||
rec := &cacheRecord{
|
rec := &cacheRecord{
|
||||||
mu: &sync.Mutex{},
|
mu: &sync.Mutex{},
|
||||||
cm: cm,
|
cm: cm,
|
||||||
refs: make(map[ref]struct{}),
|
refs: make(map[ref]struct{}),
|
||||||
parent: mutable.parentRef(false),
|
parent: mutable.parentRef(false, dhs),
|
||||||
md: md,
|
md: md,
|
||||||
equalMutable: &mutableRef{cacheRecord: mutable},
|
equalMutable: &mutableRef{cacheRecord: mutable},
|
||||||
}
|
}
|
||||||
|
@ -393,25 +442,39 @@ func (cm *cacheManager) getRecord(ctx context.Context, id string, opts ...RefOpt
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := setImageRefMetadata(rec, opts...); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to append image ref metadata to ref %s", rec.ID())
|
||||||
|
}
|
||||||
|
|
||||||
cm.records[id] = rec
|
cm.records[id] = rec
|
||||||
|
if err := checkLazyProviders(rec); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return rec, nil
|
return rec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cm *cacheManager) New(ctx context.Context, s ImmutableRef, opts ...RefOption) (mr MutableRef, err error) {
|
func (cm *cacheManager) New(ctx context.Context, s ImmutableRef, sess session.Group, opts ...RefOption) (mr MutableRef, err error) {
|
||||||
id := identity.NewID()
|
id := identity.NewID()
|
||||||
|
|
||||||
var parent *immutableRef
|
var parent *immutableRef
|
||||||
var parentID string
|
var parentID string
|
||||||
var parentSnapshotID string
|
var parentSnapshotID string
|
||||||
if s != nil {
|
if s != nil {
|
||||||
p, err := cm.Get(ctx, s.ID(), NoUpdateLastUsed)
|
if _, ok := s.(*immutableRef); ok {
|
||||||
|
parent = s.Clone().(*immutableRef)
|
||||||
|
} else {
|
||||||
|
p, err := cm.Get(ctx, s.ID(), append(opts, NoUpdateLastUsed)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := p.Finalize(ctx, true); err != nil {
|
parent = p.(*immutableRef)
|
||||||
|
}
|
||||||
|
if err := parent.Finalize(ctx, true); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := parent.Extract(ctx, sess); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
parent = p.(*immutableRef)
|
|
||||||
parentSnapshotID = getSnapshotID(parent.md)
|
parentSnapshotID = getSnapshotID(parent.md)
|
||||||
parentID = parent.ID()
|
parentID = parent.ID()
|
||||||
}
|
}
|
||||||
|
@ -469,18 +532,28 @@ func (cm *cacheManager) New(ctx context.Context, s ImmutableRef, opts ...RefOpti
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := setImageRefMetadata(rec, opts...); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to append image ref metadata to ref %s", rec.ID())
|
||||||
|
}
|
||||||
|
|
||||||
cm.mu.Lock()
|
cm.mu.Lock()
|
||||||
defer cm.mu.Unlock()
|
defer cm.mu.Unlock()
|
||||||
|
|
||||||
cm.records[id] = rec // TODO: save to db
|
cm.records[id] = rec // TODO: save to db
|
||||||
|
|
||||||
return rec.mref(true), nil
|
// parent refs are possibly lazy so keep it hold the description handlers.
|
||||||
|
var dhs DescHandlers
|
||||||
|
if parent != nil {
|
||||||
|
dhs = parent.descHandlers
|
||||||
|
}
|
||||||
|
return rec.mref(true, dhs), nil
|
||||||
}
|
}
|
||||||
func (cm *cacheManager) GetMutable(ctx context.Context, id string) (MutableRef, error) {
|
|
||||||
|
func (cm *cacheManager) GetMutable(ctx context.Context, id string, opts ...RefOption) (MutableRef, error) {
|
||||||
cm.mu.Lock()
|
cm.mu.Lock()
|
||||||
defer cm.mu.Unlock()
|
defer cm.mu.Unlock()
|
||||||
|
|
||||||
rec, err := cm.getRecord(ctx, id)
|
rec, err := cm.getRecord(ctx, id, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -506,7 +579,7 @@ func (cm *cacheManager) GetMutable(ctx context.Context, id string) (MutableRef,
|
||||||
rec.equalImmutable = nil
|
rec.equalImmutable = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return rec.mref(true), nil
|
return rec.mref(true, descHandlersOf(opts...)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cm *cacheManager) Prune(ctx context.Context, ch chan client.UsageInfo, opts ...client.PruneInfo) error {
|
func (cm *cacheManager) Prune(ctx context.Context, ch chan client.UsageInfo, opts ...client.PruneInfo) error {
|
||||||
|
@ -957,6 +1030,31 @@ func WithCreationTime(tm time.Time) RefOption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Need a separate type for imageRef because it needs to be called outside
|
||||||
|
// initializeMetadata while still being a RefOption, so wrapping it in a
|
||||||
|
// different type ensures initializeMetadata won't catch it too and duplicate
|
||||||
|
// setting the metadata.
|
||||||
|
type imageRefOption func(m withMetadata) error
|
||||||
|
|
||||||
|
// WithImageRef appends the given imageRef to the cache ref's metadata
|
||||||
|
func WithImageRef(imageRef string) RefOption {
|
||||||
|
return imageRefOption(func(m withMetadata) error {
|
||||||
|
return appendImageRef(m.Metadata(), imageRef)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func setImageRefMetadata(m withMetadata, opts ...RefOption) error {
|
||||||
|
md := m.Metadata()
|
||||||
|
for _, opt := range opts {
|
||||||
|
if fn, ok := opt.(imageRefOption); ok {
|
||||||
|
if err := fn(m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return md.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
func initializeMetadata(m withMetadata, parent string, opts ...RefOption) error {
|
func initializeMetadata(m withMetadata, parent string, opts ...RefOption) error {
|
||||||
md := m.Metadata()
|
md := m.Metadata()
|
||||||
if tm := GetCreatedAt(md); !tm.IsZero() {
|
if tm := GetCreatedAt(md); !tm.IsZero() {
|
||||||
|
|
61
vendor/github.com/moby/buildkit/cache/metadata.go
generated
vendored
61
vendor/github.com/moby/buildkit/cache/metadata.go
generated
vendored
|
@ -28,6 +28,10 @@ const keyBlob = "cache.blob"
|
||||||
const keySnapshot = "cache.snapshot"
|
const keySnapshot = "cache.snapshot"
|
||||||
const keyBlobOnly = "cache.blobonly"
|
const keyBlobOnly = "cache.blobonly"
|
||||||
const keyMediaType = "cache.mediatype"
|
const keyMediaType = "cache.mediatype"
|
||||||
|
const keyImageRefs = "cache.imageRefs"
|
||||||
|
|
||||||
|
// BlobSize is the packed blob size as specified in the oci descriptor
|
||||||
|
const keyBlobSize = "cache.blobsize"
|
||||||
|
|
||||||
const keyDeleted = "cache.deleted"
|
const keyDeleted = "cache.deleted"
|
||||||
|
|
||||||
|
@ -307,6 +311,63 @@ func getSize(si *metadata.StorageItem) int64 {
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func appendImageRef(si *metadata.StorageItem, s string) error {
|
||||||
|
return si.GetAndSetValue(keyImageRefs, func(v *metadata.Value) (*metadata.Value, error) {
|
||||||
|
var imageRefs []string
|
||||||
|
if v != nil {
|
||||||
|
if err := v.Unmarshal(&imageRefs); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, existing := range imageRefs {
|
||||||
|
if existing == s {
|
||||||
|
return nil, metadata.ErrSkipSetValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imageRefs = append(imageRefs, s)
|
||||||
|
v, err := metadata.NewValue(imageRefs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to create imageRefs value")
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func getImageRefs(si *metadata.StorageItem) []string {
|
||||||
|
v := si.Get(keyImageRefs)
|
||||||
|
if v == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var refs []string
|
||||||
|
if err := v.Unmarshal(&refs); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return refs
|
||||||
|
}
|
||||||
|
|
||||||
|
func queueBlobSize(si *metadata.StorageItem, s int64) error {
|
||||||
|
v, err := metadata.NewValue(s)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to create blobsize value")
|
||||||
|
}
|
||||||
|
si.Queue(func(b *bolt.Bucket) error {
|
||||||
|
return si.SetValue(b, keyBlobSize, v)
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBlobSize(si *metadata.StorageItem) int64 {
|
||||||
|
v := si.Get(keyBlobSize)
|
||||||
|
if v == nil {
|
||||||
|
return sizeUnknown
|
||||||
|
}
|
||||||
|
var size int64
|
||||||
|
if err := v.Unmarshal(&size); err != nil {
|
||||||
|
return sizeUnknown
|
||||||
|
}
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
func getEqualMutable(si *metadata.StorageItem) string {
|
func getEqualMutable(si *metadata.StorageItem) string {
|
||||||
v := si.Get(keyEqualMutable)
|
v := si.Get(keyEqualMutable)
|
||||||
if v == nil {
|
if v == nil {
|
||||||
|
|
16
vendor/github.com/moby/buildkit/cache/metadata/metadata.go
generated
vendored
16
vendor/github.com/moby/buildkit/cache/metadata/metadata.go
generated
vendored
|
@ -372,6 +372,22 @@ func (s *StorageItem) SetValue(b *bolt.Bucket, key string, v *Value) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ErrSkipSetValue = errors.New("skip setting metadata value")
|
||||||
|
|
||||||
|
func (s *StorageItem) GetAndSetValue(key string, fn func(*Value) (*Value, error)) error {
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
return s.Update(func(b *bolt.Bucket) error {
|
||||||
|
v, err := fn(s.values[key])
|
||||||
|
if errors.Is(err, ErrSkipSetValue) {
|
||||||
|
return nil
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return s.SetValue(b, key, v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type Value struct {
|
type Value struct {
|
||||||
Value json.RawMessage `json:"value,omitempty"`
|
Value json.RawMessage `json:"value,omitempty"`
|
||||||
Index string `json:"index,omitempty"`
|
Index string `json:"index,omitempty"`
|
||||||
|
|
35
vendor/github.com/moby/buildkit/cache/opts.go
generated
vendored
Normal file
35
vendor/github.com/moby/buildkit/cache/opts.go
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/moby/buildkit/session"
|
||||||
|
"github.com/moby/buildkit/util/progress"
|
||||||
|
digest "github.com/opencontainers/go-digest"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DescHandler struct {
|
||||||
|
Provider func(session.Group) content.Provider
|
||||||
|
Progress progress.Controller
|
||||||
|
SnapshotLabels map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
type DescHandlers map[digest.Digest]*DescHandler
|
||||||
|
|
||||||
|
func descHandlersOf(opts ...RefOption) DescHandlers {
|
||||||
|
for _, opt := range opts {
|
||||||
|
if opt, ok := opt.(DescHandlers); ok {
|
||||||
|
return opt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DescHandlerKey digest.Digest
|
||||||
|
|
||||||
|
type NeedsRemoteProvidersError []digest.Digest
|
||||||
|
|
||||||
|
func (m NeedsRemoteProvidersError) Error() string {
|
||||||
|
return fmt.Sprintf("missing descriptor handlers for lazy blobs %+v", []digest.Digest(m))
|
||||||
|
}
|
325
vendor/github.com/moby/buildkit/cache/refs.go
generated
vendored
325
vendor/github.com/moby/buildkit/cache/refs.go
generated
vendored
|
@ -14,14 +14,18 @@ import (
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
"github.com/moby/buildkit/cache/metadata"
|
"github.com/moby/buildkit/cache/metadata"
|
||||||
"github.com/moby/buildkit/identity"
|
"github.com/moby/buildkit/identity"
|
||||||
|
"github.com/moby/buildkit/session"
|
||||||
"github.com/moby/buildkit/snapshot"
|
"github.com/moby/buildkit/snapshot"
|
||||||
|
"github.com/moby/buildkit/solver"
|
||||||
|
"github.com/moby/buildkit/util/compression"
|
||||||
"github.com/moby/buildkit/util/flightcontrol"
|
"github.com/moby/buildkit/util/flightcontrol"
|
||||||
"github.com/moby/buildkit/util/leaseutil"
|
"github.com/moby/buildkit/util/leaseutil"
|
||||||
|
"github.com/moby/buildkit/util/winlayers"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
imagespecidentity "github.com/opencontainers/image-spec/identity"
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ref is a reference to cacheable objects.
|
// Ref is a reference to cacheable objects.
|
||||||
|
@ -41,8 +45,8 @@ type ImmutableRef interface {
|
||||||
Clone() ImmutableRef
|
Clone() ImmutableRef
|
||||||
|
|
||||||
Info() RefInfo
|
Info() RefInfo
|
||||||
SetBlob(ctx context.Context, desc ocispec.Descriptor) error
|
Extract(ctx context.Context, s session.Group) error // +progress
|
||||||
Extract(ctx context.Context) error // +progress
|
GetRemote(ctx context.Context, createIfNeeded bool, compressionType compression.Type, s session.Group) (*solver.Remote, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type RefInfo struct {
|
type RefInfo struct {
|
||||||
|
@ -61,7 +65,7 @@ type MutableRef interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mountable interface {
|
type Mountable interface {
|
||||||
Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error)
|
Mount(ctx context.Context, readonly bool, s session.Group) (snapshot.Mountable, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ref interface {
|
type ref interface {
|
||||||
|
@ -93,15 +97,23 @@ type cacheRecord struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// hold ref lock before calling
|
// hold ref lock before calling
|
||||||
func (cr *cacheRecord) ref(triggerLastUsed bool) *immutableRef {
|
func (cr *cacheRecord) ref(triggerLastUsed bool, descHandlers DescHandlers) *immutableRef {
|
||||||
ref := &immutableRef{cacheRecord: cr, triggerLastUsed: triggerLastUsed}
|
ref := &immutableRef{
|
||||||
|
cacheRecord: cr,
|
||||||
|
triggerLastUsed: triggerLastUsed,
|
||||||
|
descHandlers: descHandlers,
|
||||||
|
}
|
||||||
cr.refs[ref] = struct{}{}
|
cr.refs[ref] = struct{}{}
|
||||||
return ref
|
return ref
|
||||||
}
|
}
|
||||||
|
|
||||||
// hold ref lock before calling
|
// hold ref lock before calling
|
||||||
func (cr *cacheRecord) mref(triggerLastUsed bool) *mutableRef {
|
func (cr *cacheRecord) mref(triggerLastUsed bool, descHandlers DescHandlers) *mutableRef {
|
||||||
ref := &mutableRef{cacheRecord: cr, triggerLastUsed: triggerLastUsed}
|
ref := &mutableRef{
|
||||||
|
cacheRecord: cr,
|
||||||
|
triggerLastUsed: triggerLastUsed,
|
||||||
|
descHandlers: descHandlers,
|
||||||
|
}
|
||||||
cr.refs[ref] = struct{}{}
|
cr.refs[ref] = struct{}{}
|
||||||
return ref
|
return ref
|
||||||
}
|
}
|
||||||
|
@ -131,6 +143,22 @@ func (cr *cacheRecord) isDead() bool {
|
||||||
return cr.dead || (cr.equalImmutable != nil && cr.equalImmutable.dead) || (cr.equalMutable != nil && cr.equalMutable.dead)
|
return cr.dead || (cr.equalImmutable != nil && cr.equalImmutable.dead) || (cr.equalMutable != nil && cr.equalMutable.dead)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cr *cacheRecord) isLazy(ctx context.Context) (bool, error) {
|
||||||
|
if !getBlobOnly(cr.md) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
dgst := getBlob(cr.md)
|
||||||
|
// special case for moby where there is no compressed blob (empty digest)
|
||||||
|
if dgst == "" {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
_, err := cr.cm.ContentStore.Info(ctx, digest.Digest(dgst))
|
||||||
|
if errors.Is(err, errdefs.ErrNotFound) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
func (cr *cacheRecord) IdentityMapping() *idtools.IdentityMapping {
|
func (cr *cacheRecord) IdentityMapping() *idtools.IdentityMapping {
|
||||||
return cr.cm.IdentityMapping()
|
return cr.cm.IdentityMapping()
|
||||||
}
|
}
|
||||||
|
@ -186,27 +214,18 @@ func (cr *cacheRecord) Size(ctx context.Context) (int64, error) {
|
||||||
return s.(int64), nil
|
return s.(int64), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cr *cacheRecord) Parent() ImmutableRef {
|
func (cr *cacheRecord) parentRef(hidden bool, descHandlers DescHandlers) *immutableRef {
|
||||||
if p := cr.parentRef(true); p != nil { // avoid returning typed nil pointer
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cr *cacheRecord) parentRef(hidden bool) *immutableRef {
|
|
||||||
p := cr.parent
|
p := cr.parent
|
||||||
if p == nil {
|
if p == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
return p.ref(hidden)
|
return p.ref(hidden, descHandlers)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cr *cacheRecord) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
|
// must be called holding cacheRecord mu
|
||||||
cr.mu.Lock()
|
func (cr *cacheRecord) mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
|
||||||
defer cr.mu.Unlock()
|
|
||||||
|
|
||||||
if cr.mutable {
|
if cr.mutable {
|
||||||
m, err := cr.cm.Snapshotter.Mounts(ctx, getSnapshotID(cr.md))
|
m, err := cr.cm.Snapshotter.Mounts(ctx, getSnapshotID(cr.md))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -282,20 +301,29 @@ func (cr *cacheRecord) ID() string {
|
||||||
type immutableRef struct {
|
type immutableRef struct {
|
||||||
*cacheRecord
|
*cacheRecord
|
||||||
triggerLastUsed bool
|
triggerLastUsed bool
|
||||||
|
descHandlers DescHandlers
|
||||||
}
|
}
|
||||||
|
|
||||||
type mutableRef struct {
|
type mutableRef struct {
|
||||||
*cacheRecord
|
*cacheRecord
|
||||||
triggerLastUsed bool
|
triggerLastUsed bool
|
||||||
|
descHandlers DescHandlers
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sr *immutableRef) Clone() ImmutableRef {
|
func (sr *immutableRef) Clone() ImmutableRef {
|
||||||
sr.mu.Lock()
|
sr.mu.Lock()
|
||||||
ref := sr.ref(false)
|
ref := sr.ref(false, sr.descHandlers)
|
||||||
sr.mu.Unlock()
|
sr.mu.Unlock()
|
||||||
return ref
|
return ref
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sr *immutableRef) Parent() ImmutableRef {
|
||||||
|
if p := sr.parentRef(true, sr.descHandlers); p != nil { // avoid returning typed nil pointer
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (sr *immutableRef) Info() RefInfo {
|
func (sr *immutableRef) Info() RefInfo {
|
||||||
return RefInfo{
|
return RefInfo{
|
||||||
ChainID: digest.Digest(getChainID(sr.md)),
|
ChainID: digest.Digest(getChainID(sr.md)),
|
||||||
|
@ -308,25 +336,181 @@ func (sr *immutableRef) Info() RefInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sr *immutableRef) Extract(ctx context.Context) error {
|
func (sr *immutableRef) ociDesc() (ocispec.Descriptor, error) {
|
||||||
_, err := sr.sizeG.Do(ctx, sr.ID()+"-extract", func(ctx context.Context) (interface{}, error) {
|
desc := ocispec.Descriptor{
|
||||||
|
Digest: digest.Digest(getBlob(sr.md)),
|
||||||
|
Size: getBlobSize(sr.md),
|
||||||
|
MediaType: getMediaType(sr.md),
|
||||||
|
Annotations: make(map[string]string),
|
||||||
|
}
|
||||||
|
|
||||||
|
diffID := getDiffID(sr.md)
|
||||||
|
if diffID != "" {
|
||||||
|
desc.Annotations["containerd.io/uncompressed"] = diffID
|
||||||
|
}
|
||||||
|
|
||||||
|
createdAt := GetCreatedAt(sr.md)
|
||||||
|
if !createdAt.IsZero() {
|
||||||
|
createdAt, err := createdAt.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
return ocispec.Descriptor{}, err
|
||||||
|
}
|
||||||
|
desc.Annotations["buildkit/createdat"] = string(createdAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
return desc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// order is from parent->child, sr will be at end of slice
|
||||||
|
func (sr *immutableRef) parentRefChain() []*immutableRef {
|
||||||
|
var count int
|
||||||
|
for ref := sr; ref != nil; ref = ref.parent {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
refs := make([]*immutableRef, count)
|
||||||
|
for i, ref := count-1, sr; ref != nil; i, ref = i-1, ref.parent {
|
||||||
|
refs[i] = ref
|
||||||
|
}
|
||||||
|
return refs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sr *immutableRef) Mount(ctx context.Context, readonly bool, s session.Group) (snapshot.Mountable, error) {
|
||||||
|
if err := sr.Extract(ctx, s); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sr.mu.Lock()
|
||||||
|
defer sr.mu.Unlock()
|
||||||
|
return sr.mount(ctx, readonly)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sr *immutableRef) Extract(ctx context.Context, s session.Group) (rerr error) {
|
||||||
|
if !getBlobOnly(sr.md) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, done, err := leaseutil.WithLease(ctx, sr.cm.LeaseManager, leaseutil.MakeTemporary)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer done(ctx)
|
||||||
|
|
||||||
|
if GetLayerType(sr) == "windows" {
|
||||||
|
ctx = winlayers.UseWindowsLayerMode(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := sr.prepareRemoteSnapshots(ctx, sr.descHandlers); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return sr.extract(ctx, sr.descHandlers, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sr *immutableRef) prepareRemoteSnapshots(ctx context.Context, dhs DescHandlers) (bool, error) {
|
||||||
|
ok, err := sr.sizeG.Do(ctx, sr.ID()+"-prepare-remote-snapshot", func(ctx context.Context) (_ interface{}, rerr error) {
|
||||||
snapshotID := getSnapshotID(sr.md)
|
snapshotID := getSnapshotID(sr.md)
|
||||||
if _, err := sr.cm.Snapshotter.Stat(ctx, snapshotID); err == nil {
|
if _, err := sr.cm.Snapshotter.Stat(ctx, snapshotID); err == nil {
|
||||||
queueBlobOnly(sr.md, false)
|
return true, nil
|
||||||
return nil, sr.md.Commit()
|
}
|
||||||
|
desc, err := sr.ociDesc()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
dh := dhs[desc.Digest]
|
||||||
|
if dh == nil {
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
parentID := ""
|
parentID := ""
|
||||||
if sr.parent != nil {
|
if sr.parent != nil {
|
||||||
if err := sr.parent.Extract(ctx); err != nil {
|
if ok, err := sr.parent.prepareRemoteSnapshots(ctx, dhs); !ok {
|
||||||
return nil, err
|
return false, err
|
||||||
}
|
}
|
||||||
parentID = getSnapshotID(sr.parent.md)
|
parentID = getSnapshotID(sr.parent.md)
|
||||||
}
|
}
|
||||||
info := sr.Info()
|
|
||||||
key := fmt.Sprintf("extract-%s %s", identity.NewID(), info.ChainID)
|
|
||||||
|
|
||||||
err := sr.cm.Snapshotter.Prepare(ctx, key, parentID)
|
// Hint labels to the snapshotter
|
||||||
|
labels := dh.SnapshotLabels
|
||||||
|
if labels == nil {
|
||||||
|
labels = make(map[string]string)
|
||||||
|
}
|
||||||
|
labels["containerd.io/snapshot.ref"] = snapshotID
|
||||||
|
opt := snapshots.WithLabels(labels)
|
||||||
|
|
||||||
|
// Try to preapre the remote snapshot
|
||||||
|
key := fmt.Sprintf("tmp-%s %s", identity.NewID(), sr.Info().ChainID)
|
||||||
|
if err = sr.cm.Snapshotter.Prepare(ctx, key, parentID, opt); err != nil {
|
||||||
|
if errdefs.IsAlreadyExists(err) {
|
||||||
|
// Check if the targeting snapshot ID has been prepared as a remote
|
||||||
|
// snapshot in the snapshotter.
|
||||||
|
if _, err := sr.cm.Snapshotter.Stat(ctx, snapshotID); err == nil {
|
||||||
|
// We can use this remote snapshot without unlazying.
|
||||||
|
// Try the next layer as well.
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This layer cannot be prepared without unlazying.
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
return ok.(bool), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sr *immutableRef) extract(ctx context.Context, dhs DescHandlers, s session.Group) error {
|
||||||
|
_, err := sr.sizeG.Do(ctx, sr.ID()+"-extract", func(ctx context.Context) (_ interface{}, rerr error) {
|
||||||
|
snapshotID := getSnapshotID(sr.md)
|
||||||
|
if _, err := sr.cm.Snapshotter.Stat(ctx, snapshotID); err == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if sr.cm.Applier == nil {
|
||||||
|
return nil, errors.New("extract requires an applier")
|
||||||
|
}
|
||||||
|
|
||||||
|
eg, egctx := errgroup.WithContext(ctx)
|
||||||
|
|
||||||
|
parentID := ""
|
||||||
|
if sr.parent != nil {
|
||||||
|
eg.Go(func() error {
|
||||||
|
if err := sr.parent.extract(egctx, dhs, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
parentID = getSnapshotID(sr.parent.md)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
desc, err := sr.ociDesc()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
dh := dhs[desc.Digest]
|
||||||
|
|
||||||
|
eg.Go(func() error {
|
||||||
|
// unlazies if needed, otherwise a no-op
|
||||||
|
return lazyRefProvider{
|
||||||
|
ref: sr,
|
||||||
|
desc: desc,
|
||||||
|
dh: dh,
|
||||||
|
session: s,
|
||||||
|
}.Unlazy(egctx)
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := eg.Wait(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if dh != nil && dh.Progress != nil {
|
||||||
|
_, stopProgress := dh.Progress.Start(ctx)
|
||||||
|
defer stopProgress(rerr)
|
||||||
|
statusDone := dh.Progress.Status("extracting "+desc.Digest.String(), "extracting")
|
||||||
|
defer statusDone()
|
||||||
|
}
|
||||||
|
|
||||||
|
key := fmt.Sprintf("extract-%s %s", identity.NewID(), sr.Info().ChainID)
|
||||||
|
|
||||||
|
err = sr.cm.Snapshotter.Prepare(ctx, key, parentID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -339,10 +523,7 @@ func (sr *immutableRef) Extract(ctx context.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
_, err = sr.cm.Applier.Apply(ctx, ocispec.Descriptor{
|
_, err = sr.cm.Applier.Apply(ctx, desc, mounts)
|
||||||
Digest: info.Blob,
|
|
||||||
MediaType: info.MediaType,
|
|
||||||
}, mounts)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
unmount()
|
unmount()
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -357,6 +538,7 @@ func (sr *immutableRef) Extract(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
queueBlobOnly(sr.md, false)
|
queueBlobOnly(sr.md, false)
|
||||||
|
setSize(sr.md, sizeUnknown)
|
||||||
if err := sr.md.Commit(); err != nil {
|
if err := sr.md.Commit(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -365,65 +547,6 @@ func (sr *immutableRef) Extract(ctx context.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetBlob associates a blob with the cache record.
|
|
||||||
// A lease must be held for the blob when calling this function
|
|
||||||
// Caller should call Info() for knowing what current values are actually set
|
|
||||||
func (sr *immutableRef) SetBlob(ctx context.Context, desc ocispec.Descriptor) error {
|
|
||||||
diffID, err := diffIDFromDescriptor(desc)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := sr.cm.ContentStore.Info(ctx, desc.Digest); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
sr.mu.Lock()
|
|
||||||
defer sr.mu.Unlock()
|
|
||||||
|
|
||||||
if getChainID(sr.md) != "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := sr.finalize(ctx, true); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
p := sr.parent
|
|
||||||
var parentChainID digest.Digest
|
|
||||||
var parentBlobChainID digest.Digest
|
|
||||||
if p != nil {
|
|
||||||
pInfo := p.Info()
|
|
||||||
if pInfo.ChainID == "" || pInfo.BlobChainID == "" {
|
|
||||||
return errors.Errorf("failed to set blob for reference with non-addressable parent")
|
|
||||||
}
|
|
||||||
parentChainID = pInfo.ChainID
|
|
||||||
parentBlobChainID = pInfo.BlobChainID
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := sr.cm.LeaseManager.AddResource(ctx, leases.Lease{ID: sr.ID()}, leases.Resource{
|
|
||||||
ID: desc.Digest.String(),
|
|
||||||
Type: "content",
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
queueDiffID(sr.md, diffID.String())
|
|
||||||
queueBlob(sr.md, desc.Digest.String())
|
|
||||||
chainID := diffID
|
|
||||||
blobChainID := imagespecidentity.ChainID([]digest.Digest{desc.Digest, diffID})
|
|
||||||
if parentChainID != "" {
|
|
||||||
chainID = imagespecidentity.ChainID([]digest.Digest{parentChainID, chainID})
|
|
||||||
blobChainID = imagespecidentity.ChainID([]digest.Digest{parentBlobChainID, blobChainID})
|
|
||||||
}
|
|
||||||
queueChainID(sr.md, chainID.String())
|
|
||||||
queueBlobChainID(sr.md, blobChainID.String())
|
|
||||||
queueMediaType(sr.md, desc.MediaType)
|
|
||||||
if err := sr.md.Commit(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sr *immutableRef) Release(ctx context.Context) error {
|
func (sr *immutableRef) Release(ctx context.Context) error {
|
||||||
sr.cm.mu.Lock()
|
sr.cm.mu.Lock()
|
||||||
defer sr.cm.mu.Unlock()
|
defer sr.cm.mu.Unlock()
|
||||||
|
@ -555,7 +678,7 @@ func (sr *mutableRef) commit(ctx context.Context) (*immutableRef, error) {
|
||||||
rec := &cacheRecord{
|
rec := &cacheRecord{
|
||||||
mu: sr.mu,
|
mu: sr.mu,
|
||||||
cm: sr.cm,
|
cm: sr.cm,
|
||||||
parent: sr.parentRef(false),
|
parent: sr.parentRef(false, sr.descHandlers),
|
||||||
equalMutable: sr,
|
equalMutable: sr,
|
||||||
refs: make(map[ref]struct{}),
|
refs: make(map[ref]struct{}),
|
||||||
md: md,
|
md: md,
|
||||||
|
@ -588,13 +711,16 @@ func (sr *mutableRef) commit(ctx context.Context) (*immutableRef, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ref := rec.ref(true)
|
ref := rec.ref(true, sr.descHandlers)
|
||||||
sr.equalImmutable = ref
|
sr.equalImmutable = ref
|
||||||
return ref, nil
|
return ref, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sr *mutableRef) updatesLastUsed() bool {
|
func (sr *mutableRef) Mount(ctx context.Context, readonly bool, s session.Group) (snapshot.Mountable, error) {
|
||||||
return sr.triggerLastUsed
|
sr.mu.Lock()
|
||||||
|
defer sr.mu.Unlock()
|
||||||
|
|
||||||
|
return sr.mount(ctx, readonly)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sr *mutableRef) Commit(ctx context.Context) (ImmutableRef, error) {
|
func (sr *mutableRef) Commit(ctx context.Context) (ImmutableRef, error) {
|
||||||
|
@ -633,12 +759,11 @@ func (sr *mutableRef) release(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sr.remove(ctx, true)
|
return sr.remove(ctx, true)
|
||||||
} else {
|
}
|
||||||
if sr.updateLastUsed() {
|
if sr.updateLastUsed() {
|
||||||
updateLastUsed(sr.md)
|
updateLastUsed(sr.md)
|
||||||
sr.triggerLastUsed = false
|
sr.triggerLastUsed = false
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
204
vendor/github.com/moby/buildkit/cache/remote.go
generated
vendored
Normal file
204
vendor/github.com/moby/buildkit/cache/remote.go
generated
vendored
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
|
"github.com/containerd/containerd/reference"
|
||||||
|
"github.com/moby/buildkit/session"
|
||||||
|
"github.com/moby/buildkit/solver"
|
||||||
|
"github.com/moby/buildkit/util/compression"
|
||||||
|
"github.com/moby/buildkit/util/contentutil"
|
||||||
|
"github.com/moby/buildkit/util/leaseutil"
|
||||||
|
"github.com/moby/buildkit/util/pull/pullprogress"
|
||||||
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Unlazier interface {
|
||||||
|
Unlazy(ctx context.Context) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRemote gets a *solver.Remote from content store for this ref (potentially pulling lazily).
|
||||||
|
// Note: Use WorkerRef.GetRemote instead as moby integration requires custom GetRemote implementation.
|
||||||
|
func (sr *immutableRef) GetRemote(ctx context.Context, createIfNeeded bool, compressionType compression.Type, s session.Group) (*solver.Remote, error) {
|
||||||
|
ctx, done, err := leaseutil.WithLease(ctx, sr.cm.LeaseManager, leaseutil.MakeTemporary)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer done(ctx)
|
||||||
|
|
||||||
|
err = sr.computeBlobChain(ctx, createIfNeeded, compressionType, s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mprovider := &lazyMultiProvider{mprovider: contentutil.NewMultiProvider(nil)}
|
||||||
|
remote := &solver.Remote{
|
||||||
|
Provider: mprovider,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ref := range sr.parentRefChain() {
|
||||||
|
desc, err := ref.ociDesc()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: The media type might be missing for some migrated ones
|
||||||
|
// from before lease based storage. If so, we should detect
|
||||||
|
// the media type from blob data.
|
||||||
|
//
|
||||||
|
// Discussion: https://github.com/moby/buildkit/pull/1277#discussion_r352795429
|
||||||
|
if desc.MediaType == "" {
|
||||||
|
desc.MediaType, err = compression.DetectLayerMediaType(ctx, sr.cm.ContentStore, desc.Digest, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update distribution source annotation for lazy-refs (non-lazy refs
|
||||||
|
// will already have their dsl stored in the content store, which is
|
||||||
|
// used by the push handlers)
|
||||||
|
if isLazy, err := ref.isLazy(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if isLazy {
|
||||||
|
imageRefs := getImageRefs(ref.md)
|
||||||
|
for _, imageRef := range imageRefs {
|
||||||
|
refspec, err := reference.Parse(imageRef)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := url.Parse("dummy://" + refspec.Locator)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
source, repo := u.Hostname(), strings.TrimPrefix(u.Path, "/")
|
||||||
|
if desc.Annotations == nil {
|
||||||
|
desc.Annotations = make(map[string]string)
|
||||||
|
}
|
||||||
|
dslKey := fmt.Sprintf("%s.%s", "containerd.io/distribution.source", source)
|
||||||
|
|
||||||
|
var existingRepos []string
|
||||||
|
if existings, ok := desc.Annotations[dslKey]; ok {
|
||||||
|
existingRepos = strings.Split(existings, ",")
|
||||||
|
}
|
||||||
|
addNewRepo := true
|
||||||
|
for _, existing := range existingRepos {
|
||||||
|
if existing == repo {
|
||||||
|
addNewRepo = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if addNewRepo {
|
||||||
|
existingRepos = append(existingRepos, repo)
|
||||||
|
}
|
||||||
|
desc.Annotations[dslKey] = strings.Join(existingRepos, ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remote.Descriptors = append(remote.Descriptors, desc)
|
||||||
|
mprovider.Add(lazyRefProvider{
|
||||||
|
ref: ref,
|
||||||
|
desc: desc,
|
||||||
|
dh: sr.descHandlers[desc.Digest],
|
||||||
|
session: s,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return remote, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type lazyMultiProvider struct {
|
||||||
|
mprovider *contentutil.MultiProvider
|
||||||
|
plist []lazyRefProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mp *lazyMultiProvider) Add(p lazyRefProvider) {
|
||||||
|
mp.mprovider.Add(p.desc.Digest, p)
|
||||||
|
mp.plist = append(mp.plist, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mp *lazyMultiProvider) ReaderAt(ctx context.Context, desc ocispec.Descriptor) (content.ReaderAt, error) {
|
||||||
|
return mp.mprovider.ReaderAt(ctx, desc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mp *lazyMultiProvider) Unlazy(ctx context.Context) error {
|
||||||
|
eg, egctx := errgroup.WithContext(ctx)
|
||||||
|
for _, p := range mp.plist {
|
||||||
|
p := p
|
||||||
|
eg.Go(func() error {
|
||||||
|
return p.Unlazy(egctx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return eg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
type lazyRefProvider struct {
|
||||||
|
ref *immutableRef
|
||||||
|
desc ocispec.Descriptor
|
||||||
|
dh *DescHandler
|
||||||
|
session session.Group
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p lazyRefProvider) ReaderAt(ctx context.Context, desc ocispec.Descriptor) (content.ReaderAt, error) {
|
||||||
|
if desc.Digest != p.desc.Digest {
|
||||||
|
return nil, errdefs.ErrNotFound
|
||||||
|
}
|
||||||
|
if err := p.Unlazy(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return p.ref.cm.ContentStore.ReaderAt(ctx, desc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p lazyRefProvider) Unlazy(ctx context.Context) error {
|
||||||
|
_, err := p.ref.cm.unlazyG.Do(ctx, string(p.desc.Digest), func(ctx context.Context) (_ interface{}, rerr error) {
|
||||||
|
if isLazy, err := p.ref.isLazy(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if !isLazy {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.dh == nil {
|
||||||
|
// shouldn't happen, if you have a lazy immutable ref it already should be validated
|
||||||
|
// that descriptor handlers exist for it
|
||||||
|
return nil, errors.New("unexpected nil descriptor handler")
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.dh.Progress != nil {
|
||||||
|
var stopProgress func(error)
|
||||||
|
ctx, stopProgress = p.dh.Progress.Start(ctx)
|
||||||
|
defer stopProgress(rerr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// For now, just pull down the whole content and then return a ReaderAt from the local content
|
||||||
|
// store. If efficient partial reads are desired in the future, something more like a "tee"
|
||||||
|
// that caches remote partial reads to a local store may need to replace this.
|
||||||
|
err := contentutil.Copy(ctx, p.ref.cm.ContentStore, &pullprogress.ProviderWithProgress{
|
||||||
|
Provider: p.dh.Provider(p.session),
|
||||||
|
Manager: p.ref.cm.ContentStore,
|
||||||
|
}, p.desc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if imageRefs := getImageRefs(p.ref.md); len(imageRefs) > 0 {
|
||||||
|
// just use the first image ref, it's arbitrary
|
||||||
|
imageRef := imageRefs[0]
|
||||||
|
if GetDescription(p.ref.md) == "" {
|
||||||
|
queueDescription(p.ref.md, "pulled from "+imageRef)
|
||||||
|
err := p.ref.md.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
23
vendor/github.com/moby/buildkit/cache/remotecache/export.go
generated
vendored
23
vendor/github.com/moby/buildkit/cache/remotecache/export.go
generated
vendored
|
@ -12,6 +12,7 @@ import (
|
||||||
v1 "github.com/moby/buildkit/cache/remotecache/v1"
|
v1 "github.com/moby/buildkit/cache/remotecache/v1"
|
||||||
"github.com/moby/buildkit/session"
|
"github.com/moby/buildkit/session"
|
||||||
"github.com/moby/buildkit/solver"
|
"github.com/moby/buildkit/solver"
|
||||||
|
"github.com/moby/buildkit/util/compression"
|
||||||
"github.com/moby/buildkit/util/contentutil"
|
"github.com/moby/buildkit/util/contentutil"
|
||||||
"github.com/moby/buildkit/util/progress"
|
"github.com/moby/buildkit/util/progress"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
|
@ -55,20 +56,17 @@ type contentCacheExporter struct {
|
||||||
solver.CacheExporterTarget
|
solver.CacheExporterTarget
|
||||||
chains *v1.CacheChains
|
chains *v1.CacheChains
|
||||||
ingester content.Ingester
|
ingester content.Ingester
|
||||||
|
oci bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewExporter(ingester content.Ingester) Exporter {
|
func NewExporter(ingester content.Ingester, oci bool) Exporter {
|
||||||
cc := v1.NewCacheChains()
|
cc := v1.NewCacheChains()
|
||||||
return &contentCacheExporter{CacheExporterTarget: cc, chains: cc, ingester: ingester}
|
return &contentCacheExporter{CacheExporterTarget: cc, chains: cc, ingester: ingester, oci: oci}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ce *contentCacheExporter) Finalize(ctx context.Context) (map[string]string, error) {
|
func (ce *contentCacheExporter) Finalize(ctx context.Context) (map[string]string, error) {
|
||||||
return export(ctx, ce.ingester, ce.chains)
|
|
||||||
}
|
|
||||||
|
|
||||||
func export(ctx context.Context, ingester content.Ingester, cc *v1.CacheChains) (map[string]string, error) {
|
|
||||||
res := make(map[string]string)
|
res := make(map[string]string)
|
||||||
config, descs, err := cc.Marshal()
|
config, descs, err := ce.chains.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -86,6 +84,9 @@ func export(ctx context.Context, ingester content.Ingester, cc *v1.CacheChains)
|
||||||
var mfst manifestList
|
var mfst manifestList
|
||||||
mfst.SchemaVersion = 2
|
mfst.SchemaVersion = 2
|
||||||
mfst.MediaType = images.MediaTypeDockerSchema2ManifestList
|
mfst.MediaType = images.MediaTypeDockerSchema2ManifestList
|
||||||
|
if ce.oci {
|
||||||
|
mfst.MediaType = ocispec.MediaTypeImageIndex
|
||||||
|
}
|
||||||
|
|
||||||
for _, l := range config.Layers {
|
for _, l := range config.Layers {
|
||||||
dgstPair, ok := descs[l.Blob]
|
dgstPair, ok := descs[l.Blob]
|
||||||
|
@ -93,13 +94,15 @@ func export(ctx context.Context, ingester content.Ingester, cc *v1.CacheChains)
|
||||||
return nil, errors.Errorf("missing blob %s", l.Blob)
|
return nil, errors.Errorf("missing blob %s", l.Blob)
|
||||||
}
|
}
|
||||||
layerDone := oneOffProgress(ctx, fmt.Sprintf("writing layer %s", l.Blob))
|
layerDone := oneOffProgress(ctx, fmt.Sprintf("writing layer %s", l.Blob))
|
||||||
if err := contentutil.Copy(ctx, ingester, dgstPair.Provider, dgstPair.Descriptor); err != nil {
|
if err := contentutil.Copy(ctx, ce.ingester, dgstPair.Provider, dgstPair.Descriptor); err != nil {
|
||||||
return nil, layerDone(errors.Wrap(err, "error writing layer blob"))
|
return nil, layerDone(errors.Wrap(err, "error writing layer blob"))
|
||||||
}
|
}
|
||||||
layerDone(nil)
|
layerDone(nil)
|
||||||
mfst.Manifests = append(mfst.Manifests, dgstPair.Descriptor)
|
mfst.Manifests = append(mfst.Manifests, dgstPair.Descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mfst.Manifests = compression.ConvertAllLayerMediaTypes(ce.oci, mfst.Manifests...)
|
||||||
|
|
||||||
dt, err := json.Marshal(config)
|
dt, err := json.Marshal(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -111,7 +114,7 @@ func export(ctx context.Context, ingester content.Ingester, cc *v1.CacheChains)
|
||||||
MediaType: v1.CacheConfigMediaTypeV0,
|
MediaType: v1.CacheConfigMediaTypeV0,
|
||||||
}
|
}
|
||||||
configDone := oneOffProgress(ctx, fmt.Sprintf("writing config %s", dgst))
|
configDone := oneOffProgress(ctx, fmt.Sprintf("writing config %s", dgst))
|
||||||
if err := content.WriteBlob(ctx, ingester, dgst.String(), bytes.NewReader(dt), desc); err != nil {
|
if err := content.WriteBlob(ctx, ce.ingester, dgst.String(), bytes.NewReader(dt), desc); err != nil {
|
||||||
return nil, configDone(errors.Wrap(err, "error writing config blob"))
|
return nil, configDone(errors.Wrap(err, "error writing config blob"))
|
||||||
}
|
}
|
||||||
configDone(nil)
|
configDone(nil)
|
||||||
|
@ -130,7 +133,7 @@ func export(ctx context.Context, ingester content.Ingester, cc *v1.CacheChains)
|
||||||
MediaType: mfst.MediaType,
|
MediaType: mfst.MediaType,
|
||||||
}
|
}
|
||||||
mfstDone := oneOffProgress(ctx, fmt.Sprintf("writing manifest %s", dgst))
|
mfstDone := oneOffProgress(ctx, fmt.Sprintf("writing manifest %s", dgst))
|
||||||
if err := content.WriteBlob(ctx, ingester, dgst.String(), bytes.NewReader(dt), desc); err != nil {
|
if err := content.WriteBlob(ctx, ce.ingester, dgst.String(), bytes.NewReader(dt), desc); err != nil {
|
||||||
return nil, mfstDone(errors.Wrap(err, "error writing manifest blob"))
|
return nil, mfstDone(errors.Wrap(err, "error writing manifest blob"))
|
||||||
}
|
}
|
||||||
descJSON, err := json.Marshal(desc)
|
descJSON, err := json.Marshal(desc)
|
||||||
|
|
14
vendor/github.com/moby/buildkit/cache/remotecache/local/local.go
generated
vendored
14
vendor/github.com/moby/buildkit/cache/remotecache/local/local.go
generated
vendored
|
@ -2,6 +2,7 @@ package local
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
@ -17,6 +18,7 @@ const (
|
||||||
attrDigest = "digest"
|
attrDigest = "digest"
|
||||||
attrSrc = "src"
|
attrSrc = "src"
|
||||||
attrDest = "dest"
|
attrDest = "dest"
|
||||||
|
attrOCIMediatypes = "oci-mediatypes"
|
||||||
contentStoreIDPrefix = "local:"
|
contentStoreIDPrefix = "local:"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,12 +29,20 @@ func ResolveCacheExporterFunc(sm *session.Manager) remotecache.ResolveCacheExpor
|
||||||
if store == "" {
|
if store == "" {
|
||||||
return nil, errors.New("local cache exporter requires dest")
|
return nil, errors.New("local cache exporter requires dest")
|
||||||
}
|
}
|
||||||
|
ociMediatypes := true
|
||||||
|
if v, ok := attrs[attrOCIMediatypes]; ok {
|
||||||
|
b, err := strconv.ParseBool(v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to parse %s", attrOCIMediatypes)
|
||||||
|
}
|
||||||
|
ociMediatypes = b
|
||||||
|
}
|
||||||
csID := contentStoreIDPrefix + store
|
csID := contentStoreIDPrefix + store
|
||||||
cs, err := getContentStore(ctx, sm, g, csID)
|
cs, err := getContentStore(ctx, sm, g, csID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return remotecache.NewExporter(cs), nil
|
return remotecache.NewExporter(cs, ociMediatypes), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +86,7 @@ func getContentStore(ctx context.Context, sm *session.Manager, g session.Group,
|
||||||
timeoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
timeoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
caller, err := sm.Get(timeoutCtx, sessionID)
|
caller, err := sm.Get(timeoutCtx, sessionID, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
16
vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go
generated
vendored
16
vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go
generated
vendored
|
@ -2,6 +2,7 @@ package registry
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
"github.com/containerd/containerd/remotes/docker"
|
"github.com/containerd/containerd/remotes/docker"
|
||||||
|
@ -29,6 +30,7 @@ func canonicalizeRef(rawRef string) (string, error) {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
attrRef = "ref"
|
attrRef = "ref"
|
||||||
|
attrOCIMediatypes = "oci-mediatypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ResolveCacheExporterFunc(sm *session.Manager, hosts docker.RegistryHosts) remotecache.ResolveCacheExporterFunc {
|
func ResolveCacheExporterFunc(sm *session.Manager, hosts docker.RegistryHosts) remotecache.ResolveCacheExporterFunc {
|
||||||
|
@ -37,12 +39,20 @@ func ResolveCacheExporterFunc(sm *session.Manager, hosts docker.RegistryHosts) r
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
remote := resolver.New(hosts, resolver.NewSessionAuthenticator(sm, g))
|
ociMediatypes := true
|
||||||
|
if v, ok := attrs[attrOCIMediatypes]; ok {
|
||||||
|
b, err := strconv.ParseBool(v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to parse %s", attrOCIMediatypes)
|
||||||
|
}
|
||||||
|
ociMediatypes = b
|
||||||
|
}
|
||||||
|
remote := resolver.DefaultPool.GetResolver(hosts, ref, "push", sm, g)
|
||||||
pusher, err := remote.Pusher(ctx, ref)
|
pusher, err := remote.Pusher(ctx, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return remotecache.NewExporter(contentutil.FromPusher(pusher)), nil
|
return remotecache.NewExporter(contentutil.FromPusher(pusher), ociMediatypes), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +62,7 @@ func ResolveCacheImporterFunc(sm *session.Manager, cs content.Store, hosts docke
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, specs.Descriptor{}, err
|
return nil, specs.Descriptor{}, err
|
||||||
}
|
}
|
||||||
remote := resolver.New(hosts, resolver.NewSessionAuthenticator(sm, g))
|
remote := resolver.DefaultPool.GetResolver(hosts, ref, "pull", sm, g)
|
||||||
xref, desc, err := remote.Resolve(ctx, ref)
|
xref, desc, err := remote.Resolve(ctx, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, specs.Descriptor{}, err
|
return nil, specs.Descriptor{}, err
|
||||||
|
|
3
vendor/github.com/moby/buildkit/cache/remotecache/v1/cachestorage.go
generated
vendored
3
vendor/github.com/moby/buildkit/cache/remotecache/v1/cachestorage.go
generated
vendored
|
@ -5,6 +5,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/moby/buildkit/identity"
|
"github.com/moby/buildkit/identity"
|
||||||
|
"github.com/moby/buildkit/session"
|
||||||
"github.com/moby/buildkit/solver"
|
"github.com/moby/buildkit/solver"
|
||||||
"github.com/moby/buildkit/worker"
|
"github.com/moby/buildkit/worker"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
|
@ -260,7 +261,7 @@ func (cs *cacheResultStorage) Load(ctx context.Context, res solver.CacheResult)
|
||||||
return worker.NewWorkerRefResult(ref, cs.w), nil
|
return worker.NewWorkerRefResult(ref, cs.w), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *cacheResultStorage) LoadRemote(ctx context.Context, res solver.CacheResult) (*solver.Remote, error) {
|
func (cs *cacheResultStorage) LoadRemote(ctx context.Context, res solver.CacheResult, _ session.Group) (*solver.Remote, error) {
|
||||||
if r := cs.byResultID(res.ID); r != nil && r.result != nil {
|
if r := cs.byResultID(res.ID); r != nil && r.result != nil {
|
||||||
return r.result, nil
|
return r.result, nil
|
||||||
}
|
}
|
||||||
|
|
39
vendor/github.com/moby/buildkit/cache/remotecache/v1/chains.go
generated
vendored
39
vendor/github.com/moby/buildkit/cache/remotecache/v1/chains.go
generated
vendored
|
@ -23,7 +23,7 @@ func (c *CacheChains) Add(dgst digest.Digest) solver.CacheExporterRecord {
|
||||||
if strings.HasPrefix(dgst.String(), "random:") {
|
if strings.HasPrefix(dgst.String(), "random:") {
|
||||||
return &nopRecord{}
|
return &nopRecord{}
|
||||||
}
|
}
|
||||||
it := &item{c: c, dgst: dgst}
|
it := &item{c: c, dgst: dgst, backlinks: map[*item]struct{}{}}
|
||||||
c.items = append(c.items, it)
|
c.items = append(c.items, it)
|
||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,17 @@ func (c *CacheChains) normalize() error {
|
||||||
byKey: map[digest.Digest]*item{},
|
byKey: map[digest.Digest]*item{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validated := make([]*item, 0, len(c.items))
|
||||||
|
for _, it := range c.items {
|
||||||
|
it.validate()
|
||||||
|
}
|
||||||
|
for _, it := range c.items {
|
||||||
|
if !it.invalid {
|
||||||
|
validated = append(validated, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.items = validated
|
||||||
|
|
||||||
for _, it := range c.items {
|
for _, it := range c.items {
|
||||||
_, err := normalizeItem(it, st)
|
_, err := normalizeItem(it, st)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -100,6 +111,8 @@ type item struct {
|
||||||
resultTime time.Time
|
resultTime time.Time
|
||||||
|
|
||||||
links []map[link]struct{}
|
links []map[link]struct{}
|
||||||
|
backlinks map[*item]struct{}
|
||||||
|
invalid bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type link struct {
|
type link struct {
|
||||||
|
@ -126,6 +139,30 @@ func (c *item) LinkFrom(rec solver.CacheExporterRecord, index int, selector stri
|
||||||
}
|
}
|
||||||
|
|
||||||
c.links[index][link{src: src, selector: selector}] = struct{}{}
|
c.links[index][link{src: src, selector: selector}] = struct{}{}
|
||||||
|
src.backlinks[c] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *item) validate() {
|
||||||
|
for _, m := range c.links {
|
||||||
|
if len(m) == 0 {
|
||||||
|
c.invalid = true
|
||||||
|
for bl := range c.backlinks {
|
||||||
|
changed := false
|
||||||
|
for _, m := range bl.links {
|
||||||
|
for l := range m {
|
||||||
|
if l.src == c {
|
||||||
|
delete(m, l)
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if changed {
|
||||||
|
bl.validate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *item) walkAllResults(fn func(i *item) error, visited map[*item]struct{}) error {
|
func (c *item) walkAllResults(fn func(i *item) error, visited map[*item]struct{}) error {
|
||||||
|
|
11
vendor/github.com/moby/buildkit/cache/remotecache/v1/utils.go
generated
vendored
11
vendor/github.com/moby/buildkit/cache/remotecache/v1/utils.go
generated
vendored
|
@ -4,10 +4,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/moby/buildkit/exporter/containerimage/exptypes"
|
||||||
"github.com/moby/buildkit/solver"
|
"github.com/moby/buildkit/solver"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -230,10 +229,6 @@ func marshalRemote(r *solver.Remote, state *marshalState) string {
|
||||||
if len(r.Descriptors) == 0 {
|
if len(r.Descriptors) == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
type Remote struct {
|
|
||||||
Descriptors []ocispec.Descriptor
|
|
||||||
Provider content.Provider
|
|
||||||
}
|
|
||||||
var parentID string
|
var parentID string
|
||||||
if len(r.Descriptors) > 1 {
|
if len(r.Descriptors) > 1 {
|
||||||
r2 := &solver.Remote{
|
r2 := &solver.Remote{
|
||||||
|
@ -244,6 +239,10 @@ func marshalRemote(r *solver.Remote, state *marshalState) string {
|
||||||
}
|
}
|
||||||
desc := r.Descriptors[len(r.Descriptors)-1]
|
desc := r.Descriptors[len(r.Descriptors)-1]
|
||||||
|
|
||||||
|
if desc.Digest == exptypes.EmptyGZLayer {
|
||||||
|
return parentID
|
||||||
|
}
|
||||||
|
|
||||||
state.descriptors[desc.Digest] = DescriptorProviderPair{
|
state.descriptors[desc.Digest] = DescriptorProviderPair{
|
||||||
Descriptor: desc,
|
Descriptor: desc,
|
||||||
Provider: r.Provider,
|
Provider: r.Provider,
|
||||||
|
|
20
vendor/github.com/moby/buildkit/cache/util/fsutil.go
generated
vendored
20
vendor/github.com/moby/buildkit/cache/util/fsutil.go
generated
vendored
|
@ -8,7 +8,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/containerd/continuity/fs"
|
"github.com/containerd/continuity/fs"
|
||||||
"github.com/moby/buildkit/cache"
|
|
||||||
"github.com/moby/buildkit/snapshot"
|
"github.com/moby/buildkit/snapshot"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/tonistiigi/fsutil"
|
"github.com/tonistiigi/fsutil"
|
||||||
|
@ -25,12 +24,7 @@ type FileRange struct {
|
||||||
Length int
|
Length int
|
||||||
}
|
}
|
||||||
|
|
||||||
func withMount(ctx context.Context, ref cache.ImmutableRef, cb func(string) error) error {
|
func withMount(ctx context.Context, mount snapshot.Mountable, cb func(string) error) error {
|
||||||
mount, err := ref.Mount(ctx, true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
lm := snapshot.LocalMounter(mount)
|
lm := snapshot.LocalMounter(mount)
|
||||||
|
|
||||||
root, err := lm.Mount()
|
root, err := lm.Mount()
|
||||||
|
@ -55,10 +49,10 @@ func withMount(ctx context.Context, ref cache.ImmutableRef, cb func(string) erro
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadFile(ctx context.Context, ref cache.ImmutableRef, req ReadRequest) ([]byte, error) {
|
func ReadFile(ctx context.Context, mount snapshot.Mountable, req ReadRequest) ([]byte, error) {
|
||||||
var dt []byte
|
var dt []byte
|
||||||
|
|
||||||
err := withMount(ctx, ref, func(root string) error {
|
err := withMount(ctx, mount, func(root string) error {
|
||||||
fp, err := fs.RootPath(root, req.Filename)
|
fp, err := fs.RootPath(root, req.Filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
|
@ -90,7 +84,7 @@ type ReadDirRequest struct {
|
||||||
IncludePattern string
|
IncludePattern string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadDir(ctx context.Context, ref cache.ImmutableRef, req ReadDirRequest) ([]*fstypes.Stat, error) {
|
func ReadDir(ctx context.Context, mount snapshot.Mountable, req ReadDirRequest) ([]*fstypes.Stat, error) {
|
||||||
var (
|
var (
|
||||||
rd []*fstypes.Stat
|
rd []*fstypes.Stat
|
||||||
wo fsutil.WalkOpt
|
wo fsutil.WalkOpt
|
||||||
|
@ -98,7 +92,7 @@ func ReadDir(ctx context.Context, ref cache.ImmutableRef, req ReadDirRequest) ([
|
||||||
if req.IncludePattern != "" {
|
if req.IncludePattern != "" {
|
||||||
wo.IncludePatterns = append(wo.IncludePatterns, req.IncludePattern)
|
wo.IncludePatterns = append(wo.IncludePatterns, req.IncludePattern)
|
||||||
}
|
}
|
||||||
err := withMount(ctx, ref, func(root string) error {
|
err := withMount(ctx, mount, func(root string) error {
|
||||||
fp, err := fs.RootPath(root, req.Path)
|
fp, err := fs.RootPath(root, req.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
|
@ -123,9 +117,9 @@ func ReadDir(ctx context.Context, ref cache.ImmutableRef, req ReadDirRequest) ([
|
||||||
return rd, err
|
return rd, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func StatFile(ctx context.Context, ref cache.ImmutableRef, path string) (*fstypes.Stat, error) {
|
func StatFile(ctx context.Context, mount snapshot.Mountable, path string) (*fstypes.Stat, error) {
|
||||||
var st *fstypes.Stat
|
var st *fstypes.Stat
|
||||||
err := withMount(ctx, ref, func(root string) error {
|
err := withMount(ctx, mount, func(root string) error {
|
||||||
fp, err := fs.RootPath(root, path)
|
fp, err := fs.RootPath(root, path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
|
|
46
vendor/github.com/moby/buildkit/client/build.go
generated
vendored
46
vendor/github.com/moby/buildkit/client/build.go
generated
vendored
|
@ -45,11 +45,14 @@ func (c *Client) Build(ctx context.Context, opt SolveOpt, product string, buildF
|
||||||
}
|
}
|
||||||
|
|
||||||
cb := func(ref string, s *session.Session) error {
|
cb := func(ref string, s *session.Session) error {
|
||||||
g, err := grpcclient.New(ctx, feOpts, s.ID(), product, c.gatewayClientForBuild(ref), gworkers)
|
gwClient := c.gatewayClientForBuild(ref)
|
||||||
|
g, err := grpcclient.New(ctx, feOpts, s.ID(), product, gwClient, gworkers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gwClient.caps = g.BuildOpts().Caps
|
||||||
|
|
||||||
if err := g.Run(ctx, buildFunc); err != nil {
|
if err := g.Run(ctx, buildFunc); err != nil {
|
||||||
return errors.Wrap(err, "failed to run Build function")
|
return errors.Wrap(err, "failed to run Build function")
|
||||||
}
|
}
|
||||||
|
@ -59,14 +62,18 @@ func (c *Client) Build(ctx context.Context, opt SolveOpt, product string, buildF
|
||||||
return c.solve(ctx, nil, cb, opt, statusChan)
|
return c.solve(ctx, nil, cb, opt, statusChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) gatewayClientForBuild(buildid string) gatewayapi.LLBBridgeClient {
|
func (c *Client) gatewayClientForBuild(buildid string) *gatewayClientForBuild {
|
||||||
g := gatewayapi.NewLLBBridgeClient(c.conn)
|
g := gatewayapi.NewLLBBridgeClient(c.conn)
|
||||||
return &gatewayClientForBuild{g, buildid}
|
return &gatewayClientForBuild{
|
||||||
|
gateway: g,
|
||||||
|
buildID: buildid,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type gatewayClientForBuild struct {
|
type gatewayClientForBuild struct {
|
||||||
gateway gatewayapi.LLBBridgeClient
|
gateway gatewayapi.LLBBridgeClient
|
||||||
buildID string
|
buildID string
|
||||||
|
caps apicaps.CapSet
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *gatewayClientForBuild) ResolveImageConfig(ctx context.Context, in *gatewayapi.ResolveImageConfigRequest, opts ...grpc.CallOption) (*gatewayapi.ResolveImageConfigResponse, error) {
|
func (g *gatewayClientForBuild) ResolveImageConfig(ctx context.Context, in *gatewayapi.ResolveImageConfigRequest, opts ...grpc.CallOption) (*gatewayapi.ResolveImageConfigResponse, error) {
|
||||||
|
@ -85,11 +92,17 @@ func (g *gatewayClientForBuild) ReadFile(ctx context.Context, in *gatewayapi.Rea
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *gatewayClientForBuild) ReadDir(ctx context.Context, in *gatewayapi.ReadDirRequest, opts ...grpc.CallOption) (*gatewayapi.ReadDirResponse, error) {
|
func (g *gatewayClientForBuild) ReadDir(ctx context.Context, in *gatewayapi.ReadDirRequest, opts ...grpc.CallOption) (*gatewayapi.ReadDirResponse, error) {
|
||||||
|
if err := g.caps.Supports(gatewayapi.CapReadDir); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
|
ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
|
||||||
return g.gateway.ReadDir(ctx, in, opts...)
|
return g.gateway.ReadDir(ctx, in, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *gatewayClientForBuild) StatFile(ctx context.Context, in *gatewayapi.StatFileRequest, opts ...grpc.CallOption) (*gatewayapi.StatFileResponse, error) {
|
func (g *gatewayClientForBuild) StatFile(ctx context.Context, in *gatewayapi.StatFileRequest, opts ...grpc.CallOption) (*gatewayapi.StatFileResponse, error) {
|
||||||
|
if err := g.caps.Supports(gatewayapi.CapStatFile); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
|
ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
|
||||||
return g.gateway.StatFile(ctx, in, opts...)
|
return g.gateway.StatFile(ctx, in, opts...)
|
||||||
}
|
}
|
||||||
|
@ -105,6 +118,33 @@ func (g *gatewayClientForBuild) Return(ctx context.Context, in *gatewayapi.Retur
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *gatewayClientForBuild) Inputs(ctx context.Context, in *gatewayapi.InputsRequest, opts ...grpc.CallOption) (*gatewayapi.InputsResponse, error) {
|
func (g *gatewayClientForBuild) Inputs(ctx context.Context, in *gatewayapi.InputsRequest, opts ...grpc.CallOption) (*gatewayapi.InputsResponse, error) {
|
||||||
|
if err := g.caps.Supports(gatewayapi.CapFrontendInputs); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
|
ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
|
||||||
return g.gateway.Inputs(ctx, in, opts...)
|
return g.gateway.Inputs(ctx, in, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *gatewayClientForBuild) NewContainer(ctx context.Context, in *gatewayapi.NewContainerRequest, opts ...grpc.CallOption) (*gatewayapi.NewContainerResponse, error) {
|
||||||
|
if err := g.caps.Supports(gatewayapi.CapGatewayExec); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
|
||||||
|
return g.gateway.NewContainer(ctx, in, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gatewayClientForBuild) ReleaseContainer(ctx context.Context, in *gatewayapi.ReleaseContainerRequest, opts ...grpc.CallOption) (*gatewayapi.ReleaseContainerResponse, error) {
|
||||||
|
if err := g.caps.Supports(gatewayapi.CapGatewayExec); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
|
||||||
|
return g.gateway.ReleaseContainer(ctx, in, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gatewayClientForBuild) ExecProcess(ctx context.Context, opts ...grpc.CallOption) (gatewayapi.LLBBridge_ExecProcessClient, error) {
|
||||||
|
if err := g.caps.Supports(gatewayapi.CapGatewayExec); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
|
||||||
|
return g.gateway.ExecProcess(ctx, opts...)
|
||||||
|
}
|
||||||
|
|
35
vendor/github.com/moby/buildkit/client/client.go
generated
vendored
35
vendor/github.com/moby/buildkit/client/client.go
generated
vendored
|
@ -6,8 +6,9 @@ import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/defaults"
|
||||||
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
||||||
"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
|
"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
|
||||||
controlapi "github.com/moby/buildkit/api/services/control"
|
controlapi "github.com/moby/buildkit/api/services/control"
|
||||||
|
@ -30,7 +31,10 @@ type ClientOpt interface{}
|
||||||
|
|
||||||
// New returns a new buildkit client. Address can be empty for the system-default address.
|
// New returns a new buildkit client. Address can be empty for the system-default address.
|
||||||
func New(ctx context.Context, address string, opts ...ClientOpt) (*Client, error) {
|
func New(ctx context.Context, address string, opts ...ClientOpt) (*Client, error) {
|
||||||
gopts := []grpc.DialOption{}
|
gopts := []grpc.DialOption{
|
||||||
|
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize)),
|
||||||
|
grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(defaults.DefaultMaxSendMsgSize)),
|
||||||
|
}
|
||||||
needDialer := true
|
needDialer := true
|
||||||
needWithInsecure := true
|
needWithInsecure := true
|
||||||
|
|
||||||
|
@ -54,7 +58,7 @@ func New(ctx context.Context, address string, opts ...ClientOpt) (*Client, error
|
||||||
stream = append(stream, otgrpc.OpenTracingStreamClientInterceptor(wt.tracer))
|
stream = append(stream, otgrpc.OpenTracingStreamClientInterceptor(wt.tracer))
|
||||||
}
|
}
|
||||||
if wd, ok := o.(*withDialer); ok {
|
if wd, ok := o.(*withDialer); ok {
|
||||||
gopts = append(gopts, grpc.WithDialer(wd.dialer))
|
gopts = append(gopts, grpc.WithContextDialer(wd.dialer))
|
||||||
needDialer = false
|
needDialer = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,9 +67,7 @@ func New(ctx context.Context, address string, opts ...ClientOpt) (*Client, error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// TODO(AkihiroSuda): use WithContextDialer (requires grpc 1.19)
|
gopts = append(gopts, grpc.WithContextDialer(dialFn))
|
||||||
// https://github.com/grpc/grpc-go/commit/40cb5618f475e7b9d61aa7920ae4b04ef9bbaf89
|
|
||||||
gopts = append(gopts, grpc.WithDialer(dialFn))
|
|
||||||
}
|
}
|
||||||
if needWithInsecure {
|
if needWithInsecure {
|
||||||
gopts = append(gopts, grpc.WithInsecure())
|
gopts = append(gopts, grpc.WithInsecure())
|
||||||
|
@ -74,6 +76,15 @@ func New(ctx context.Context, address string, opts ...ClientOpt) (*Client, error
|
||||||
address = appdefaults.Address
|
address = appdefaults.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// grpc-go uses a slightly different naming scheme: https://github.com/grpc/grpc/blob/master/doc/naming.md
|
||||||
|
// This will end up setting rfc non-complient :authority header to address string (e.g. tcp://127.0.0.1:1234).
|
||||||
|
// So, here sets right authority header via WithAuthority DialOption.
|
||||||
|
addressURL, err := url.Parse(address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
gopts = append(gopts, grpc.WithAuthority(addressURL.Host))
|
||||||
|
|
||||||
unary = append(unary, grpcerrors.UnaryClientInterceptor)
|
unary = append(unary, grpcerrors.UnaryClientInterceptor)
|
||||||
stream = append(stream, grpcerrors.StreamClientInterceptor)
|
stream = append(stream, grpcerrors.StreamClientInterceptor)
|
||||||
|
|
||||||
|
@ -118,10 +129,10 @@ func WithFailFast() ClientOpt {
|
||||||
}
|
}
|
||||||
|
|
||||||
type withDialer struct {
|
type withDialer struct {
|
||||||
dialer func(string, time.Duration) (net.Conn, error)
|
dialer func(context.Context, string) (net.Conn, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithDialer(df func(string, time.Duration) (net.Conn, error)) ClientOpt {
|
func WithContextDialer(df func(context.Context, string) (net.Conn, error)) ClientOpt {
|
||||||
return &withDialer{dialer: df}
|
return &withDialer{dialer: df}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,17 +190,13 @@ type withTracer struct {
|
||||||
tracer opentracing.Tracer
|
tracer opentracing.Tracer
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveDialer(address string) (func(string, time.Duration) (net.Conn, error), error) {
|
func resolveDialer(address string) (func(context.Context, string) (net.Conn, error), error) {
|
||||||
ch, err := connhelper.GetConnectionHelper(address)
|
ch, err := connhelper.GetConnectionHelper(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if ch != nil {
|
if ch != nil {
|
||||||
f := func(a string, _ time.Duration) (net.Conn, error) {
|
return ch.ContextDialer, nil
|
||||||
ctx := context.Background()
|
|
||||||
return ch.ContextDialer(ctx, a)
|
|
||||||
}
|
|
||||||
return f, nil
|
|
||||||
}
|
}
|
||||||
// basic dialer
|
// basic dialer
|
||||||
return dialer, nil
|
return dialer, nil
|
||||||
|
|
7
vendor/github.com/moby/buildkit/client/client_unix.go
generated
vendored
7
vendor/github.com/moby/buildkit/client/client_unix.go
generated
vendored
|
@ -3,17 +3,18 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func dialer(address string, timeout time.Duration) (net.Conn, error) {
|
func dialer(ctx context.Context, address string) (net.Conn, error) {
|
||||||
addrParts := strings.SplitN(address, "://", 2)
|
addrParts := strings.SplitN(address, "://", 2)
|
||||||
if len(addrParts) != 2 {
|
if len(addrParts) != 2 {
|
||||||
return nil, errors.Errorf("invalid address %s", address)
|
return nil, errors.Errorf("invalid address %s", address)
|
||||||
}
|
}
|
||||||
return net.DialTimeout(addrParts[0], addrParts[1], timeout)
|
var d net.Dialer
|
||||||
|
return d.DialContext(ctx, addrParts[0], addrParts[1])
|
||||||
}
|
}
|
||||||
|
|
9
vendor/github.com/moby/buildkit/client/client_windows.go
generated
vendored
9
vendor/github.com/moby/buildkit/client/client_windows.go
generated
vendored
|
@ -1,15 +1,15 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
winio "github.com/Microsoft/go-winio"
|
winio "github.com/Microsoft/go-winio"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func dialer(address string, timeout time.Duration) (net.Conn, error) {
|
func dialer(ctx context.Context, address string) (net.Conn, error) {
|
||||||
addrParts := strings.SplitN(address, "://", 2)
|
addrParts := strings.SplitN(address, "://", 2)
|
||||||
if len(addrParts) != 2 {
|
if len(addrParts) != 2 {
|
||||||
return nil, errors.Errorf("invalid address %s", address)
|
return nil, errors.Errorf("invalid address %s", address)
|
||||||
|
@ -17,8 +17,9 @@ func dialer(address string, timeout time.Duration) (net.Conn, error) {
|
||||||
switch addrParts[0] {
|
switch addrParts[0] {
|
||||||
case "npipe":
|
case "npipe":
|
||||||
address = strings.Replace(addrParts[1], "/", "\\", -1)
|
address = strings.Replace(addrParts[1], "/", "\\", -1)
|
||||||
return winio.DialPipe(address, &timeout)
|
return winio.DialPipeContext(ctx, address)
|
||||||
default:
|
default:
|
||||||
return net.DialTimeout(addrParts[0], addrParts[1], timeout)
|
var d net.Dialer
|
||||||
|
return d.DialContext(ctx, addrParts[0], addrParts[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
24
vendor/github.com/moby/buildkit/client/llb/definition.go
generated
vendored
24
vendor/github.com/moby/buildkit/client/llb/definition.go
generated
vendored
|
@ -24,6 +24,7 @@ type DefinitionOp struct {
|
||||||
platforms map[digest.Digest]*specs.Platform
|
platforms map[digest.Digest]*specs.Platform
|
||||||
dgst digest.Digest
|
dgst digest.Digest
|
||||||
index pb.OutputIndex
|
index pb.OutputIndex
|
||||||
|
inputCache map[digest.Digest][]*DefinitionOp
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDefinitionOp returns a new operation from a marshalled definition.
|
// NewDefinitionOp returns a new operation from a marshalled definition.
|
||||||
|
@ -96,6 +97,7 @@ func NewDefinitionOp(def *pb.Definition) (*DefinitionOp, error) {
|
||||||
platforms: platforms,
|
platforms: platforms,
|
||||||
dgst: dgst,
|
dgst: dgst,
|
||||||
index: index,
|
index: index,
|
||||||
|
inputCache: make(map[digest.Digest][]*DefinitionOp),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,14 +190,34 @@ func (d *DefinitionOp) Inputs() []Output {
|
||||||
d.mu.Unlock()
|
d.mu.Unlock()
|
||||||
|
|
||||||
for _, input := range op.Inputs {
|
for _, input := range op.Inputs {
|
||||||
vtx := &DefinitionOp{
|
var vtx *DefinitionOp
|
||||||
|
d.mu.Lock()
|
||||||
|
if existingIndexes, ok := d.inputCache[input.Digest]; ok {
|
||||||
|
if int(input.Index) < len(existingIndexes) && existingIndexes[input.Index] != nil {
|
||||||
|
vtx = existingIndexes[input.Index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if vtx == nil {
|
||||||
|
vtx = &DefinitionOp{
|
||||||
ops: d.ops,
|
ops: d.ops,
|
||||||
defs: d.defs,
|
defs: d.defs,
|
||||||
metas: d.metas,
|
metas: d.metas,
|
||||||
platforms: d.platforms,
|
platforms: d.platforms,
|
||||||
dgst: input.Digest,
|
dgst: input.Digest,
|
||||||
index: input.Index,
|
index: input.Index,
|
||||||
|
inputCache: d.inputCache,
|
||||||
}
|
}
|
||||||
|
existingIndexes := d.inputCache[input.Digest]
|
||||||
|
indexDiff := int(input.Index) - len(existingIndexes)
|
||||||
|
if indexDiff >= 0 {
|
||||||
|
// make room in the slice for the new index being set
|
||||||
|
existingIndexes = append(existingIndexes, make([]*DefinitionOp, indexDiff+1)...)
|
||||||
|
}
|
||||||
|
existingIndexes[input.Index] = vtx
|
||||||
|
d.inputCache[input.Digest] = existingIndexes
|
||||||
|
}
|
||||||
|
d.mu.Unlock()
|
||||||
|
|
||||||
inputs = append(inputs, &output{vertex: vtx, platform: platform, getIndex: func() (pb.OutputIndex, error) {
|
inputs = append(inputs, &output{vertex: vtx, platform: platform, getIndex: func() (pb.OutputIndex, error) {
|
||||||
return pb.OutputIndex(vtx.index), nil
|
return pb.OutputIndex(vtx.index), nil
|
||||||
}})
|
}})
|
||||||
|
|
28
vendor/github.com/moby/buildkit/client/llb/exec.go
generated
vendored
28
vendor/github.com/moby/buildkit/client/llb/exec.go
generated
vendored
|
@ -2,7 +2,7 @@ package llb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
_ "crypto/sha256"
|
_ "crypto/sha256" // for opencontainers/go-digest
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -153,7 +153,13 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
|
||||||
}
|
}
|
||||||
if c.Caps != nil {
|
if c.Caps != nil {
|
||||||
if err := c.Caps.Supports(pb.CapExecMetaSetsDefaultPath); err != nil {
|
if err := c.Caps.Supports(pb.CapExecMetaSetsDefaultPath); err != nil {
|
||||||
env = env.SetDefault("PATH", system.DefaultPathEnv)
|
os := "linux"
|
||||||
|
if c.Platform != nil {
|
||||||
|
os = c.Platform.OS
|
||||||
|
} else if e.constraints.Platform != nil {
|
||||||
|
os = e.constraints.Platform.OS
|
||||||
|
}
|
||||||
|
env = env.SetDefault("PATH", system.DefaultPathEnv(os))
|
||||||
} else {
|
} else {
|
||||||
addCap(&e.constraints, pb.CapExecMetaSetsDefaultPath)
|
addCap(&e.constraints, pb.CapExecMetaSetsDefaultPath)
|
||||||
}
|
}
|
||||||
|
@ -174,11 +180,17 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
|
||||||
return "", nil, nil, nil, err
|
return "", nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hostname, err := getHostname(e.base)(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
meta := &pb.Meta{
|
meta := &pb.Meta{
|
||||||
Args: args,
|
Args: args,
|
||||||
Env: env.ToArray(),
|
Env: env.ToArray(),
|
||||||
Cwd: cwd,
|
Cwd: cwd,
|
||||||
User: user,
|
User: user,
|
||||||
|
Hostname: hostname,
|
||||||
}
|
}
|
||||||
extraHosts, err := getExtraHosts(e.base)(ctx)
|
extraHosts, err := getExtraHosts(e.base)(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -217,9 +229,9 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
|
||||||
|
|
||||||
if p := e.proxyEnv; p != nil {
|
if p := e.proxyEnv; p != nil {
|
||||||
peo.Meta.ProxyEnv = &pb.ProxyEnv{
|
peo.Meta.ProxyEnv = &pb.ProxyEnv{
|
||||||
HttpProxy: p.HttpProxy,
|
HttpProxy: p.HTTPProxy,
|
||||||
HttpsProxy: p.HttpsProxy,
|
HttpsProxy: p.HTTPSProxy,
|
||||||
FtpProxy: p.FtpProxy,
|
FtpProxy: p.FTPProxy,
|
||||||
NoProxy: p.NoProxy,
|
NoProxy: p.NoProxy,
|
||||||
}
|
}
|
||||||
addCap(&e.constraints, pb.CapExecMetaProxy)
|
addCap(&e.constraints, pb.CapExecMetaProxy)
|
||||||
|
@ -629,9 +641,9 @@ type MountInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProxyEnv struct {
|
type ProxyEnv struct {
|
||||||
HttpProxy string
|
HTTPProxy string
|
||||||
HttpsProxy string
|
HTTPSProxy string
|
||||||
FtpProxy string
|
FTPProxy string
|
||||||
NoProxy string
|
NoProxy string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
22
vendor/github.com/moby/buildkit/client/llb/fileop.go
generated
vendored
22
vendor/github.com/moby/buildkit/client/llb/fileop.go
generated
vendored
|
@ -2,7 +2,7 @@ package llb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
_ "crypto/sha256"
|
_ "crypto/sha256" // for opencontainers/go-digest
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -252,13 +252,13 @@ func (co ChownOpt) SetCopyOption(mi *CopyInfo) {
|
||||||
mi.ChownOpt = &co
|
mi.ChownOpt = &co
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cp *ChownOpt) marshal(base pb.InputIndex) *pb.ChownOpt {
|
func (co *ChownOpt) marshal(base pb.InputIndex) *pb.ChownOpt {
|
||||||
if cp == nil {
|
if co == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &pb.ChownOpt{
|
return &pb.ChownOpt{
|
||||||
User: cp.User.marshal(base),
|
User: co.User.marshal(base),
|
||||||
Group: cp.Group.marshal(base),
|
Group: co.Group.marshal(base),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,17 +476,17 @@ func (a *fileActionCopy) toProtoAction(ctx context.Context, parent string, base
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fileActionCopy) sourcePath(ctx context.Context) (string, error) {
|
func (a *fileActionCopy) sourcePath(ctx context.Context) (string, error) {
|
||||||
p := path.Clean(c.src)
|
p := path.Clean(a.src)
|
||||||
if !path.IsAbs(p) {
|
if !path.IsAbs(p) {
|
||||||
if c.state != nil {
|
if a.state != nil {
|
||||||
dir, err := c.state.GetDir(ctx)
|
dir, err := a.state.GetDir(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
p = path.Join("/", dir, p)
|
p = path.Join("/", dir, p)
|
||||||
} else if c.fas != nil {
|
} else if a.fas != nil {
|
||||||
dir, err := c.fas.state.GetDir(ctx)
|
dir, err := a.fas.state.GetDir(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
2
vendor/github.com/moby/buildkit/client/llb/imagemetaresolver/resolver.go
generated
vendored
2
vendor/github.com/moby/buildkit/client/llb/imagemetaresolver/resolver.go
generated
vendored
|
@ -8,10 +8,10 @@ import (
|
||||||
"github.com/containerd/containerd/platforms"
|
"github.com/containerd/containerd/platforms"
|
||||||
"github.com/containerd/containerd/remotes"
|
"github.com/containerd/containerd/remotes"
|
||||||
"github.com/containerd/containerd/remotes/docker"
|
"github.com/containerd/containerd/remotes/docker"
|
||||||
"github.com/docker/docker/pkg/locker"
|
|
||||||
"github.com/moby/buildkit/client/llb"
|
"github.com/moby/buildkit/client/llb"
|
||||||
"github.com/moby/buildkit/util/contentutil"
|
"github.com/moby/buildkit/util/contentutil"
|
||||||
"github.com/moby/buildkit/util/imageutil"
|
"github.com/moby/buildkit/util/imageutil"
|
||||||
|
"github.com/moby/locker"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
22
vendor/github.com/moby/buildkit/client/llb/meta.go
generated
vendored
22
vendor/github.com/moby/buildkit/client/llb/meta.go
generated
vendored
|
@ -19,6 +19,7 @@ var (
|
||||||
keyDir = contextKeyT("llb.exec.dir")
|
keyDir = contextKeyT("llb.exec.dir")
|
||||||
keyEnv = contextKeyT("llb.exec.env")
|
keyEnv = contextKeyT("llb.exec.env")
|
||||||
keyUser = contextKeyT("llb.exec.user")
|
keyUser = contextKeyT("llb.exec.user")
|
||||||
|
keyHostname = contextKeyT("llb.exec.hostname")
|
||||||
keyExtraHost = contextKeyT("llb.exec.extrahost")
|
keyExtraHost = contextKeyT("llb.exec.extrahost")
|
||||||
keyPlatform = contextKeyT("llb.platform")
|
keyPlatform = contextKeyT("llb.platform")
|
||||||
keyNetwork = contextKeyT("llb.network")
|
keyNetwork = contextKeyT("llb.network")
|
||||||
|
@ -143,6 +144,25 @@ func getUser(s State) func(context.Context) (string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Hostname(str string) StateOption {
|
||||||
|
return func(s State) State {
|
||||||
|
return s.WithValue(keyHostname, str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getHostname(s State) func(context.Context) (string, error) {
|
||||||
|
return func(ctx context.Context) (string, error) {
|
||||||
|
v, err := s.getValue(keyHostname)(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if v != nil {
|
||||||
|
return v.(string), nil
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func args(args ...string) StateOption {
|
func args(args ...string) StateOption {
|
||||||
return func(s State) State {
|
return func(s State) State {
|
||||||
return s.WithValue(keyArgs, args)
|
return s.WithValue(keyArgs, args)
|
||||||
|
@ -155,7 +175,7 @@ func shlexf(str string, replace bool, v ...interface{}) StateOption {
|
||||||
}
|
}
|
||||||
return func(s State) State {
|
return func(s State) State {
|
||||||
arg, err := shlex.Split(str)
|
arg, err := shlex.Split(str)
|
||||||
if err != nil {
|
if err != nil { //nolint
|
||||||
// TODO: handle error
|
// TODO: handle error
|
||||||
}
|
}
|
||||||
return args(arg...)(s)
|
return args(arg...)(s)
|
||||||
|
|
13
vendor/github.com/moby/buildkit/client/llb/source.go
generated
vendored
13
vendor/github.com/moby/buildkit/client/llb/source.go
generated
vendored
|
@ -2,7 +2,7 @@ package llb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
_ "crypto/sha256"
|
_ "crypto/sha256" // for opencontainers/go-digest
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -233,11 +233,15 @@ func Git(remote, ref string, opts ...GitOption) State {
|
||||||
}
|
}
|
||||||
if gi.AuthTokenSecret != "" {
|
if gi.AuthTokenSecret != "" {
|
||||||
attrs[pb.AttrAuthTokenSecret] = gi.AuthTokenSecret
|
attrs[pb.AttrAuthTokenSecret] = gi.AuthTokenSecret
|
||||||
addCap(&gi.Constraints, pb.CapSourceGitHttpAuth)
|
if gi.addAuthCap {
|
||||||
|
addCap(&gi.Constraints, pb.CapSourceGitHTTPAuth)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if gi.AuthHeaderSecret != "" {
|
if gi.AuthHeaderSecret != "" {
|
||||||
attrs[pb.AttrAuthHeaderSecret] = gi.AuthHeaderSecret
|
attrs[pb.AttrAuthHeaderSecret] = gi.AuthHeaderSecret
|
||||||
addCap(&gi.Constraints, pb.CapSourceGitHttpAuth)
|
if gi.addAuthCap {
|
||||||
|
addCap(&gi.Constraints, pb.CapSourceGitHTTPAuth)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addCap(&gi.Constraints, pb.CapSourceGit)
|
addCap(&gi.Constraints, pb.CapSourceGit)
|
||||||
|
@ -260,6 +264,7 @@ type GitInfo struct {
|
||||||
KeepGitDir bool
|
KeepGitDir bool
|
||||||
AuthTokenSecret string
|
AuthTokenSecret string
|
||||||
AuthHeaderSecret string
|
AuthHeaderSecret string
|
||||||
|
addAuthCap bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func KeepGitDir() GitOption {
|
func KeepGitDir() GitOption {
|
||||||
|
@ -271,12 +276,14 @@ func KeepGitDir() GitOption {
|
||||||
func AuthTokenSecret(v string) GitOption {
|
func AuthTokenSecret(v string) GitOption {
|
||||||
return gitOptionFunc(func(gi *GitInfo) {
|
return gitOptionFunc(func(gi *GitInfo) {
|
||||||
gi.AuthTokenSecret = v
|
gi.AuthTokenSecret = v
|
||||||
|
gi.addAuthCap = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func AuthHeaderSecret(v string) GitOption {
|
func AuthHeaderSecret(v string) GitOption {
|
||||||
return gitOptionFunc(func(gi *GitInfo) {
|
return gitOptionFunc(func(gi *GitInfo) {
|
||||||
gi.AuthHeaderSecret = v
|
gi.AuthHeaderSecret = v
|
||||||
|
gi.addAuthCap = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
8
vendor/github.com/moby/buildkit/client/llb/state.go
generated
vendored
8
vendor/github.com/moby/buildkit/client/llb/state.go
generated
vendored
|
@ -320,6 +320,14 @@ func (s State) User(v string) State {
|
||||||
return User(v)(s)
|
return User(v)(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s State) Hostname(v string) State {
|
||||||
|
return Hostname(v)(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s State) GetHostname(ctx context.Context) (string, error) {
|
||||||
|
return getHostname(s)(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (s State) Platform(p specs.Platform) State {
|
func (s State) Platform(p specs.Platform) State {
|
||||||
return platform(p)(s)
|
return platform(p)(s)
|
||||||
}
|
}
|
||||||
|
|
2
vendor/github.com/moby/buildkit/client/ociindex/ociindex.go
generated
vendored
2
vendor/github.com/moby/buildkit/client/ociindex/ociindex.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/gofrs/flock"
|
"github.com/gofrs/flock"
|
||||||
"github.com/opencontainers/image-spec/specs-go/v1"
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
9
vendor/github.com/moby/buildkit/cmd/buildkitd/config/config.go
generated
vendored
9
vendor/github.com/moby/buildkit/cmd/buildkitd/config/config.go
generated
vendored
|
@ -1,5 +1,7 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
|
import "github.com/BurntSushi/toml"
|
||||||
|
|
||||||
// Config provides containerd configuration data for the server
|
// Config provides containerd configuration data for the server
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Debug bool `toml:"debug"`
|
Debug bool `toml:"debug"`
|
||||||
|
@ -79,6 +81,12 @@ type OCIConfig struct {
|
||||||
UserRemapUnsupported string `toml:"userRemapUnsupported"`
|
UserRemapUnsupported string `toml:"userRemapUnsupported"`
|
||||||
// For use in storing the OCI worker binary name that will replace buildkit-runc
|
// For use in storing the OCI worker binary name that will replace buildkit-runc
|
||||||
Binary string `toml:"binary"`
|
Binary string `toml:"binary"`
|
||||||
|
ProxySnapshotterPath string `toml:"proxySnapshotterPath"`
|
||||||
|
|
||||||
|
// StargzSnapshotterConfig is configuration for stargz snapshotter.
|
||||||
|
// Decoding this is delayed in order to remove the dependency from this
|
||||||
|
// config pkg to stargz snapshotter's config pkg.
|
||||||
|
StargzSnapshotterConfig toml.Primitive `toml:"stargzSnapshotter"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContainerdConfig struct {
|
type ContainerdConfig struct {
|
||||||
|
@ -89,6 +97,7 @@ type ContainerdConfig struct {
|
||||||
Namespace string `toml:"namespace"`
|
Namespace string `toml:"namespace"`
|
||||||
GCConfig
|
GCConfig
|
||||||
NetworkConfig
|
NetworkConfig
|
||||||
|
Snapshotter string `toml:"snapshotter"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GCPolicy struct {
|
type GCPolicy struct {
|
||||||
|
|
20
vendor/github.com/moby/buildkit/control/control.go
generated
vendored
20
vendor/github.com/moby/buildkit/control/control.go
generated
vendored
|
@ -63,7 +63,7 @@ func NewController(opt Opt) (*Controller, error) {
|
||||||
cache: cache,
|
cache: cache,
|
||||||
gatewayForwarder: gatewayForwarder,
|
gatewayForwarder: gatewayForwarder,
|
||||||
}
|
}
|
||||||
c.throttledGC = throttle.ThrottleAfter(time.Minute, c.gc)
|
c.throttledGC = throttle.After(time.Minute, c.gc)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
time.AfterFunc(time.Second, c.throttledGC)
|
time.AfterFunc(time.Second, c.throttledGC)
|
||||||
|
@ -305,6 +305,9 @@ func (c *Controller) Status(req *controlapi.StatusRequest, stream controlapi.Con
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
logSize := 0
|
||||||
|
retry := false
|
||||||
|
for {
|
||||||
sr := controlapi.StatusResponse{}
|
sr := controlapi.StatusResponse{}
|
||||||
for _, v := range ss.Vertexes {
|
for _, v := range ss.Vertexes {
|
||||||
sr.Vertexes = append(sr.Vertexes, &controlapi.Vertex{
|
sr.Vertexes = append(sr.Vertexes, &controlapi.Vertex{
|
||||||
|
@ -329,17 +332,30 @@ func (c *Controller) Status(req *controlapi.StatusRequest, stream controlapi.Con
|
||||||
Completed: v.Completed,
|
Completed: v.Completed,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for _, v := range ss.Logs {
|
for i, v := range ss.Logs {
|
||||||
sr.Logs = append(sr.Logs, &controlapi.VertexLog{
|
sr.Logs = append(sr.Logs, &controlapi.VertexLog{
|
||||||
Vertex: v.Vertex,
|
Vertex: v.Vertex,
|
||||||
Stream: int64(v.Stream),
|
Stream: int64(v.Stream),
|
||||||
Msg: v.Data,
|
Msg: v.Data,
|
||||||
Timestamp: v.Timestamp,
|
Timestamp: v.Timestamp,
|
||||||
})
|
})
|
||||||
|
logSize += len(v.Data)
|
||||||
|
// avoid logs growing big and split apart if they do
|
||||||
|
if logSize > 1024*1024 {
|
||||||
|
ss.Vertexes = nil
|
||||||
|
ss.Statuses = nil
|
||||||
|
ss.Logs = ss.Logs[i+1:]
|
||||||
|
retry = true
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err := stream.SendMsg(&sr); err != nil {
|
if err := stream.SendMsg(&sr); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if !retry {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
24
vendor/github.com/moby/buildkit/control/gateway/gateway.go
generated
vendored
24
vendor/github.com/moby/buildkit/control/gateway/gateway.go
generated
vendored
|
@ -152,3 +152,27 @@ func (gwf *GatewayForwarder) StatFile(ctx context.Context, req *gwapi.StatFileRe
|
||||||
}
|
}
|
||||||
return fwd.StatFile(ctx, req)
|
return fwd.StatFile(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gwf *GatewayForwarder) NewContainer(ctx context.Context, req *gwapi.NewContainerRequest) (*gwapi.NewContainerResponse, error) {
|
||||||
|
fwd, err := gwf.lookupForwarder(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "forwarding NewContainer")
|
||||||
|
}
|
||||||
|
return fwd.NewContainer(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gwf *GatewayForwarder) ReleaseContainer(ctx context.Context, req *gwapi.ReleaseContainerRequest) (*gwapi.ReleaseContainerResponse, error) {
|
||||||
|
fwd, err := gwf.lookupForwarder(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "forwarding ReleaseContainer")
|
||||||
|
}
|
||||||
|
return fwd.ReleaseContainer(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gwf *GatewayForwarder) ExecProcess(srv gwapi.LLBBridge_ExecProcessServer) error {
|
||||||
|
fwd, err := gwf.lookupForwarder(srv.Context())
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "forwarding ExecProcess")
|
||||||
|
}
|
||||||
|
return fwd.ExecProcess(srv)
|
||||||
|
}
|
||||||
|
|
17
vendor/github.com/moby/buildkit/executor/executor.go
generated
vendored
17
vendor/github.com/moby/buildkit/executor/executor.go
generated
vendored
|
@ -5,7 +5,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/moby/buildkit/cache"
|
"github.com/moby/buildkit/snapshot"
|
||||||
"github.com/moby/buildkit/solver/pb"
|
"github.com/moby/buildkit/solver/pb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ type Meta struct {
|
||||||
Env []string
|
Env []string
|
||||||
User string
|
User string
|
||||||
Cwd string
|
Cwd string
|
||||||
|
Hostname string
|
||||||
Tty bool
|
Tty bool
|
||||||
ReadonlyRootFS bool
|
ReadonlyRootFS bool
|
||||||
ExtraHosts []HostIP
|
ExtraHosts []HostIP
|
||||||
|
@ -21,24 +22,34 @@ type Meta struct {
|
||||||
SecurityMode pb.SecurityMode
|
SecurityMode pb.SecurityMode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Mountable interface {
|
||||||
|
Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error)
|
||||||
|
}
|
||||||
|
|
||||||
type Mount struct {
|
type Mount struct {
|
||||||
Src cache.Mountable
|
Src Mountable
|
||||||
Selector string
|
Selector string
|
||||||
Dest string
|
Dest string
|
||||||
Readonly bool
|
Readonly bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WinSize struct {
|
||||||
|
Rows uint32
|
||||||
|
Cols uint32
|
||||||
|
}
|
||||||
|
|
||||||
type ProcessInfo struct {
|
type ProcessInfo struct {
|
||||||
Meta Meta
|
Meta Meta
|
||||||
Stdin io.ReadCloser
|
Stdin io.ReadCloser
|
||||||
Stdout, Stderr io.WriteCloser
|
Stdout, Stderr io.WriteCloser
|
||||||
|
Resize <-chan WinSize
|
||||||
}
|
}
|
||||||
|
|
||||||
type Executor interface {
|
type Executor interface {
|
||||||
// Run will start a container for the given process with rootfs, mounts.
|
// Run will start a container for the given process with rootfs, mounts.
|
||||||
// `id` is an optional name for the container so it can be referenced later via Exec.
|
// `id` is an optional name for the container so it can be referenced later via Exec.
|
||||||
// `started` is an optional channel that will be closed when the container setup completes and has started running.
|
// `started` is an optional channel that will be closed when the container setup completes and has started running.
|
||||||
Run(ctx context.Context, id string, rootfs cache.Mountable, mounts []Mount, process ProcessInfo, started chan<- struct{}) error
|
Run(ctx context.Context, id string, rootfs Mount, mounts []Mount, process ProcessInfo, started chan<- struct{}) error
|
||||||
// Exec will start a process in container matching `id`. An error will be returned
|
// Exec will start a process in container matching `id`. An error will be returned
|
||||||
// if the container failed to start (via Run) or has exited before Exec is called.
|
// if the container failed to start (via Run) or has exited before Exec is called.
|
||||||
Exec(ctx context.Context, id string, process ProcessInfo) error
|
Exec(ctx context.Context, id string, process ProcessInfo) error
|
||||||
|
|
34
vendor/github.com/moby/buildkit/executor/oci/hosts.go
generated
vendored
34
vendor/github.com/moby/buildkit/executor/oci/hosts.go
generated
vendored
|
@ -14,28 +14,26 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const hostsContent = `
|
const defaultHostname = "buildkitsandbox"
|
||||||
127.0.0.1 localhost buildkitsandbox
|
|
||||||
::1 localhost ip6-localhost ip6-loopback
|
func GetHostsFile(ctx context.Context, stateDir string, extraHosts []executor.HostIP, idmap *idtools.IdentityMapping, hostname string) (string, func(), error) {
|
||||||
`
|
if len(extraHosts) != 0 || hostname != defaultHostname {
|
||||||
|
return makeHostsFile(stateDir, extraHosts, idmap, hostname)
|
||||||
|
}
|
||||||
|
|
||||||
func GetHostsFile(ctx context.Context, stateDir string, extraHosts []executor.HostIP, idmap *idtools.IdentityMapping) (string, func(), error) {
|
|
||||||
if len(extraHosts) == 0 {
|
|
||||||
_, err := g.Do(ctx, stateDir, func(ctx context.Context) (interface{}, error) {
|
_, err := g.Do(ctx, stateDir, func(ctx context.Context) (interface{}, error) {
|
||||||
_, _, err := makeHostsFile(stateDir, nil, idmap)
|
_, _, err := makeHostsFile(stateDir, nil, idmap, hostname)
|
||||||
return nil, err
|
return nil, err
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
return filepath.Join(stateDir, "hosts"), func() {}, nil
|
return filepath.Join(stateDir, "hosts"), func() {}, nil
|
||||||
}
|
|
||||||
return makeHostsFile(stateDir, extraHosts, idmap)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeHostsFile(stateDir string, extraHosts []executor.HostIP, idmap *idtools.IdentityMapping) (string, func(), error) {
|
func makeHostsFile(stateDir string, extraHosts []executor.HostIP, idmap *idtools.IdentityMapping, hostname string) (string, func(), error) {
|
||||||
p := filepath.Join(stateDir, "hosts")
|
p := filepath.Join(stateDir, "hosts")
|
||||||
if len(extraHosts) != 0 {
|
if len(extraHosts) != 0 || hostname != defaultHostname {
|
||||||
p += "." + identity.NewID()
|
p += "." + identity.NewID()
|
||||||
}
|
}
|
||||||
_, err := os.Stat(p)
|
_, err := os.Stat(p)
|
||||||
|
@ -47,8 +45,7 @@ func makeHostsFile(stateDir string, extraHosts []executor.HostIP, idmap *idtools
|
||||||
}
|
}
|
||||||
|
|
||||||
b := &bytes.Buffer{}
|
b := &bytes.Buffer{}
|
||||||
|
if _, err := b.Write([]byte(initHostsFile(hostname))); err != nil {
|
||||||
if _, err := b.Write([]byte(hostsContent)); err != nil {
|
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,3 +74,14 @@ func makeHostsFile(stateDir string, extraHosts []executor.HostIP, idmap *idtools
|
||||||
os.RemoveAll(p)
|
os.RemoveAll(p)
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initHostsFile(hostname string) string {
|
||||||
|
var hosts string
|
||||||
|
if hostname != "" {
|
||||||
|
hosts = fmt.Sprintf("127.0.0.1 localhost %s", hostname)
|
||||||
|
} else {
|
||||||
|
hosts = fmt.Sprintf("127.0.0.1 localhost %s", defaultHostname)
|
||||||
|
}
|
||||||
|
hosts = fmt.Sprintf("%s\n::1 localhost ip6-localhost ip6-loopback\n", hosts)
|
||||||
|
return hosts
|
||||||
|
}
|
||||||
|
|
119
vendor/github.com/moby/buildkit/executor/oci/mounts.go
generated
vendored
119
vendor/github.com/moby/buildkit/executor/oci/mounts.go
generated
vendored
|
@ -5,82 +5,57 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/containers"
|
||||||
|
"github.com/containerd/containerd/oci"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MountOpts sets oci spec specific info for mount points
|
func withRemovedMount(destination string) oci.SpecOpts {
|
||||||
type MountOpts func([]specs.Mount) ([]specs.Mount, error)
|
return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
|
||||||
|
newMounts := []specs.Mount{}
|
||||||
|
for _, o := range s.Mounts {
|
||||||
|
if o.Destination != destination {
|
||||||
|
newMounts = append(newMounts, o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.Mounts = newMounts
|
||||||
|
|
||||||
//GetMounts returns default required for buildkit
|
return nil
|
||||||
// https://github.com/moby/buildkit/issues/429
|
|
||||||
func GetMounts(ctx context.Context, mountOpts ...MountOpts) ([]specs.Mount, error) {
|
|
||||||
mounts := []specs.Mount{
|
|
||||||
{
|
|
||||||
Destination: "/proc",
|
|
||||||
Type: "proc",
|
|
||||||
Source: "proc",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Destination: "/dev",
|
|
||||||
Type: "tmpfs",
|
|
||||||
Source: "tmpfs",
|
|
||||||
Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Destination: "/dev/pts",
|
|
||||||
Type: "devpts",
|
|
||||||
Source: "devpts",
|
|
||||||
Options: []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Destination: "/dev/shm",
|
|
||||||
Type: "tmpfs",
|
|
||||||
Source: "shm",
|
|
||||||
Options: []string{"nosuid", "noexec", "nodev", "mode=1777", "size=65536k"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Destination: "/dev/mqueue",
|
|
||||||
Type: "mqueue",
|
|
||||||
Source: "mqueue",
|
|
||||||
Options: []string{"nosuid", "noexec", "nodev"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Destination: "/sys",
|
|
||||||
Type: "sysfs",
|
|
||||||
Source: "sysfs",
|
|
||||||
Options: []string{"nosuid", "noexec", "nodev", "ro"},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
var err error
|
|
||||||
for _, o := range mountOpts {
|
|
||||||
mounts, err = o(mounts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mounts, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func withROBind(src, dest string) func(m []specs.Mount) ([]specs.Mount, error) {
|
func withROBind(src, dest string) oci.SpecOpts {
|
||||||
return func(m []specs.Mount) ([]specs.Mount, error) {
|
return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
|
||||||
m = append(m, specs.Mount{
|
s.Mounts = append(s.Mounts, specs.Mount{
|
||||||
Destination: dest,
|
Destination: dest,
|
||||||
Type: "bind",
|
Type: "bind",
|
||||||
Source: src,
|
Source: src,
|
||||||
Options: []string{"nosuid", "noexec", "nodev", "rbind", "ro"},
|
Options: []string{"nosuid", "noexec", "nodev", "rbind", "ro"},
|
||||||
})
|
})
|
||||||
return m, nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func withCGroup() oci.SpecOpts {
|
||||||
|
return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
|
||||||
|
s.Mounts = append(s.Mounts, specs.Mount{
|
||||||
|
Destination: "/sys/fs/cgroup",
|
||||||
|
Type: "cgroup",
|
||||||
|
Source: "cgroup",
|
||||||
|
Options: []string{"ro", "nosuid", "noexec", "nodev"},
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func hasPrefix(p, prefixDir string) bool {
|
func hasPrefix(p, prefixDir string) bool {
|
||||||
prefixDir = filepath.Clean(prefixDir)
|
prefixDir = filepath.Clean(prefixDir)
|
||||||
if prefixDir == "/" {
|
if filepath.Base(prefixDir) == string(filepath.Separator) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
p = filepath.Clean(p)
|
p = filepath.Clean(p)
|
||||||
return p == prefixDir || strings.HasPrefix(p, prefixDir+"/")
|
return p == prefixDir || strings.HasPrefix(p, prefixDir+string(filepath.Separator))
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeMountsWithPrefix(mounts []specs.Mount, prefixDir string) []specs.Mount {
|
func removeMountsWithPrefix(mounts []specs.Mount, prefixDir string) []specs.Mount {
|
||||||
|
@ -93,13 +68,9 @@ func removeMountsWithPrefix(mounts []specs.Mount, prefixDir string) []specs.Moun
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func withProcessMode(processMode ProcessMode) func([]specs.Mount) ([]specs.Mount, error) {
|
func withBoundProc() oci.SpecOpts {
|
||||||
return func(m []specs.Mount) ([]specs.Mount, error) {
|
return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
|
||||||
switch processMode {
|
s.Mounts = removeMountsWithPrefix(s.Mounts, "/proc")
|
||||||
case ProcessSandbox:
|
|
||||||
// keep the default
|
|
||||||
case NoProcessSandbox:
|
|
||||||
m = removeMountsWithPrefix(m, "/proc")
|
|
||||||
procMount := specs.Mount{
|
procMount := specs.Mount{
|
||||||
Destination: "/proc",
|
Destination: "/proc",
|
||||||
Type: "bind",
|
Type: "bind",
|
||||||
|
@ -108,10 +79,24 @@ func withProcessMode(processMode ProcessMode) func([]specs.Mount) ([]specs.Mount
|
||||||
// So we keep maskedPath and readonlyPaths (although not mandatory for rootless mode)
|
// So we keep maskedPath and readonlyPaths (although not mandatory for rootless mode)
|
||||||
Options: []string{"rbind"},
|
Options: []string{"rbind"},
|
||||||
}
|
}
|
||||||
m = append([]specs.Mount{procMount}, m...)
|
s.Mounts = append([]specs.Mount{procMount}, s.Mounts...)
|
||||||
default:
|
|
||||||
return nil, errors.Errorf("unknown process mode: %v", processMode)
|
var maskedPaths []string
|
||||||
|
for _, s := range s.Linux.MaskedPaths {
|
||||||
|
if !hasPrefix(s, "/proc") {
|
||||||
|
maskedPaths = append(maskedPaths, s)
|
||||||
}
|
}
|
||||||
return m, nil
|
}
|
||||||
|
s.Linux.MaskedPaths = maskedPaths
|
||||||
|
|
||||||
|
var readonlyPaths []string
|
||||||
|
for _, s := range s.Linux.ReadonlyPaths {
|
||||||
|
if !hasPrefix(s, "/proc") {
|
||||||
|
readonlyPaths = append(readonlyPaths, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.Linux.ReadonlyPaths = readonlyPaths
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
221
vendor/github.com/moby/buildkit/executor/oci/spec.go
generated
vendored
221
vendor/github.com/moby/buildkit/executor/oci/spec.go
generated
vendored
|
@ -1,6 +1,25 @@
|
||||||
package oci
|
package oci
|
||||||
|
|
||||||
// ProcMode configures PID namespaces
|
import (
|
||||||
|
"context"
|
||||||
|
"path"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/containers"
|
||||||
|
"github.com/containerd/containerd/mount"
|
||||||
|
"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"
|
||||||
|
"github.com/moby/buildkit/util/network"
|
||||||
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProcessMode configures PID namespaces
|
||||||
type ProcessMode int
|
type ProcessMode int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -11,3 +30,203 @@ const (
|
||||||
// NoProcessSandbox should be enabled only when the BuildKit is running in a container as an unprivileged user.
|
// NoProcessSandbox should be enabled only when the BuildKit is running in a container as an unprivileged user.
|
||||||
NoProcessSandbox
|
NoProcessSandbox
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Ideally we don't have to import whole containerd just for the default spec
|
||||||
|
|
||||||
|
// 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, idmap *idtools.IdentityMapping, opts ...oci.SpecOpts) (*specs.Spec, func(), error) {
|
||||||
|
c := &containers.Container{
|
||||||
|
ID: id,
|
||||||
|
}
|
||||||
|
|
||||||
|
// containerd/oci.GenerateSpec requires a namespace, which
|
||||||
|
// will be used to namespace specs.Linux.CgroupsPath if generated
|
||||||
|
if _, ok := namespaces.Namespace(ctx); !ok {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, "buildkit")
|
||||||
|
}
|
||||||
|
|
||||||
|
if mountOpts, err := generateMountOpts(resolvConf, hostsFile); err == nil {
|
||||||
|
opts = append(opts, mountOpts...)
|
||||||
|
} else {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if securityOpts, err := generateSecurityOpts(meta.SecurityMode); err == nil {
|
||||||
|
opts = append(opts, securityOpts...)
|
||||||
|
} else {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if processModeOpts, err := generateProcessModeOpts(processMode); err == nil {
|
||||||
|
opts = append(opts, processModeOpts...)
|
||||||
|
} else {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if idmapOpts, err := generateIDmapOpts(idmap); err == nil {
|
||||||
|
opts = append(opts, idmapOpts...)
|
||||||
|
} else {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
hostname := defaultHostname
|
||||||
|
if meta.Hostname != "" {
|
||||||
|
hostname = meta.Hostname
|
||||||
|
}
|
||||||
|
|
||||||
|
opts = append(opts,
|
||||||
|
oci.WithProcessArgs(meta.Args...),
|
||||||
|
oci.WithEnv(meta.Env),
|
||||||
|
oci.WithProcessCwd(meta.Cwd),
|
||||||
|
oci.WithNewPrivileges,
|
||||||
|
oci.WithHostname(hostname),
|
||||||
|
)
|
||||||
|
|
||||||
|
s, err := oci.GenerateSpec(ctx, nil, c, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the networking information on the spec
|
||||||
|
if err := namespace.Set(s); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Process.Rlimits = nil // reset open files limit
|
||||||
|
|
||||||
|
sm := &submounts{}
|
||||||
|
|
||||||
|
var releasers []func() error
|
||||||
|
releaseAll := func() {
|
||||||
|
sm.cleanup()
|
||||||
|
for _, f := range releasers {
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, m := range mounts {
|
||||||
|
if m.Src == nil {
|
||||||
|
return nil, nil, errors.Errorf("mount %s has no source", m.Dest)
|
||||||
|
}
|
||||||
|
mountable, err := m.Src.Mount(ctx, m.Readonly)
|
||||||
|
if err != nil {
|
||||||
|
releaseAll()
|
||||||
|
return nil, nil, errors.Wrapf(err, "failed to mount %s", m.Dest)
|
||||||
|
}
|
||||||
|
mounts, release, err := mountable.Mount()
|
||||||
|
if err != nil {
|
||||||
|
releaseAll()
|
||||||
|
return nil, nil, errors.WithStack(err)
|
||||||
|
}
|
||||||
|
releasers = append(releasers, release)
|
||||||
|
for _, mount := range mounts {
|
||||||
|
mount, err = sm.subMount(mount, m.Selector)
|
||||||
|
if err != nil {
|
||||||
|
releaseAll()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
s.Mounts = append(s.Mounts, specs.Mount{
|
||||||
|
Destination: m.Dest,
|
||||||
|
Type: mount.Type,
|
||||||
|
Source: mount.Source,
|
||||||
|
Options: mount.Options,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, releaseAll, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type mountRef struct {
|
||||||
|
mount mount.Mount
|
||||||
|
unmount func() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type submounts struct {
|
||||||
|
m map[uint64]mountRef
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *submounts) subMount(m mount.Mount, subPath string) (mount.Mount, error) {
|
||||||
|
if path.Join("/", subPath) == "/" {
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
if s.m == nil {
|
||||||
|
s.m = map[uint64]mountRef{}
|
||||||
|
}
|
||||||
|
h, err := hashstructure.Hash(m, nil)
|
||||||
|
if err != nil {
|
||||||
|
return mount.Mount{}, nil
|
||||||
|
}
|
||||||
|
if mr, ok := s.m[h]; ok {
|
||||||
|
sm, err := sub(mr.mount, subPath)
|
||||||
|
if err != nil {
|
||||||
|
return mount.Mount{}, nil
|
||||||
|
}
|
||||||
|
return sm, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
lm := snapshot.LocalMounterWithMounts([]mount.Mount{m})
|
||||||
|
|
||||||
|
mp, err := lm.Mount()
|
||||||
|
if err != nil {
|
||||||
|
return mount.Mount{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
opts := []string{"rbind"}
|
||||||
|
for _, opt := range m.Options {
|
||||||
|
if opt == "ro" {
|
||||||
|
opts = append(opts, opt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.m[h] = mountRef{
|
||||||
|
mount: mount.Mount{
|
||||||
|
Source: mp,
|
||||||
|
Type: "bind",
|
||||||
|
Options: opts,
|
||||||
|
},
|
||||||
|
unmount: lm.Unmount,
|
||||||
|
}
|
||||||
|
|
||||||
|
sm, err := sub(s.m[h].mount, subPath)
|
||||||
|
if err != nil {
|
||||||
|
return mount.Mount{}, err
|
||||||
|
}
|
||||||
|
return sm, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *submounts) cleanup() {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(len(s.m))
|
||||||
|
for _, m := range s.m {
|
||||||
|
func(m mountRef) {
|
||||||
|
go func() {
|
||||||
|
m.unmount()
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}(m)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func sub(m mount.Mount, subPath string) (mount.Mount, error) {
|
||||||
|
src, err := fs.RootPath(m.Source, subPath)
|
||||||
|
if err != nil {
|
||||||
|
return mount.Mount{}, err
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
264
vendor/github.com/moby/buildkit/executor/oci/spec_unix.go
generated
vendored
264
vendor/github.com/moby/buildkit/executor/oci/spec_unix.go
generated
vendored
|
@ -3,252 +3,56 @@
|
||||||
package oci
|
package oci
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"path"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/containers"
|
|
||||||
"github.com/containerd/containerd/contrib/seccomp"
|
"github.com/containerd/containerd/contrib/seccomp"
|
||||||
"github.com/containerd/containerd/mount"
|
|
||||||
"github.com/containerd/containerd/namespaces"
|
|
||||||
"github.com/containerd/containerd/oci"
|
"github.com/containerd/containerd/oci"
|
||||||
"github.com/containerd/continuity/fs"
|
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
"github.com/mitchellh/hashstructure"
|
|
||||||
"github.com/moby/buildkit/executor"
|
|
||||||
"github.com/moby/buildkit/snapshot"
|
|
||||||
"github.com/moby/buildkit/solver/pb"
|
"github.com/moby/buildkit/solver/pb"
|
||||||
"github.com/moby/buildkit/util/entitlements/security"
|
"github.com/moby/buildkit/util/entitlements/security"
|
||||||
"github.com/moby/buildkit/util/network"
|
|
||||||
"github.com/moby/buildkit/util/system"
|
"github.com/moby/buildkit/util/system"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ideally we don't have to import whole containerd just for the default spec
|
func generateMountOpts(resolvConf, hostsFile string) ([]oci.SpecOpts, error) {
|
||||||
|
return []oci.SpecOpts{
|
||||||
// GenerateSpec generates spec using containerd functionality.
|
// https://github.com/moby/buildkit/issues/429
|
||||||
// opts are ignored for s.Process, s.Hostname, and s.Mounts .
|
withRemovedMount("/run"),
|
||||||
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,
|
|
||||||
}
|
|
||||||
_, ok := namespaces.Namespace(ctx)
|
|
||||||
if !ok {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, "buildkit")
|
|
||||||
}
|
|
||||||
if meta.SecurityMode == pb.SecurityMode_INSECURE {
|
|
||||||
opts = append(opts, security.WithInsecureSpec())
|
|
||||||
} else if system.SeccompSupported() && meta.SecurityMode == pb.SecurityMode_SANDBOX {
|
|
||||||
opts = append(opts, seccomp.WithDefaultProfile())
|
|
||||||
}
|
|
||||||
|
|
||||||
switch processMode {
|
|
||||||
case NoProcessSandbox:
|
|
||||||
// Mount for /proc is replaced in GetMounts()
|
|
||||||
opts = append(opts,
|
|
||||||
oci.WithHostNamespace(specs.PIDNamespace))
|
|
||||||
// TODO(AkihiroSuda): Configure seccomp to disable ptrace (and prctl?) explicitly
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that containerd.GenerateSpec is namespaced so as to make
|
|
||||||
// specs.Linux.CgroupsPath namespaced
|
|
||||||
s, err := oci.GenerateSpec(ctx, nil, c, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
// set the networking information on the spec
|
|
||||||
namespace.Set(s)
|
|
||||||
|
|
||||||
s.Process.Args = meta.Args
|
|
||||||
s.Process.Env = meta.Env
|
|
||||||
s.Process.Cwd = meta.Cwd
|
|
||||||
s.Process.Rlimits = nil // reset open files limit
|
|
||||||
s.Process.NoNewPrivileges = false // reset nonewprivileges
|
|
||||||
s.Hostname = "buildkitsandbox"
|
|
||||||
|
|
||||||
s.Mounts, err = GetMounts(ctx,
|
|
||||||
withProcessMode(processMode),
|
|
||||||
withROBind(resolvConf, "/etc/resolv.conf"),
|
withROBind(resolvConf, "/etc/resolv.conf"),
|
||||||
withROBind(hostsFile, "/etc/hosts"),
|
withROBind(hostsFile, "/etc/hosts"),
|
||||||
)
|
withCGroup(),
|
||||||
if err != nil {
|
}, nil
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Mounts = append(s.Mounts, specs.Mount{
|
|
||||||
Destination: "/sys/fs/cgroup",
|
|
||||||
Type: "cgroup",
|
|
||||||
Source: "cgroup",
|
|
||||||
Options: []string{"ro", "nosuid", "noexec", "nodev"},
|
|
||||||
})
|
|
||||||
|
|
||||||
if processMode == NoProcessSandbox {
|
|
||||||
var maskedPaths []string
|
|
||||||
for _, s := range s.Linux.MaskedPaths {
|
|
||||||
if !hasPrefix(s, "/proc") {
|
|
||||||
maskedPaths = append(maskedPaths, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.Linux.MaskedPaths = maskedPaths
|
|
||||||
var readonlyPaths []string
|
|
||||||
for _, s := range s.Linux.ReadonlyPaths {
|
|
||||||
if !hasPrefix(s, "/proc") {
|
|
||||||
readonlyPaths = append(readonlyPaths, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.Linux.ReadonlyPaths = readonlyPaths
|
|
||||||
}
|
|
||||||
|
|
||||||
if meta.SecurityMode == pb.SecurityMode_INSECURE {
|
|
||||||
if err = oci.WithWriteableCgroupfs(ctx, nil, c, s); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
if err = oci.WithWriteableSysfs(ctx, nil, c, s); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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{}
|
|
||||||
|
|
||||||
var releasers []func() error
|
|
||||||
releaseAll := func() {
|
|
||||||
sm.cleanup()
|
|
||||||
for _, f := range releasers {
|
|
||||||
f()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, m := range mounts {
|
|
||||||
if m.Src == nil {
|
|
||||||
return nil, nil, errors.Errorf("mount %s has no source", m.Dest)
|
|
||||||
}
|
|
||||||
mountable, err := m.Src.Mount(ctx, m.Readonly)
|
|
||||||
if err != nil {
|
|
||||||
releaseAll()
|
|
||||||
return nil, nil, errors.Wrapf(err, "failed to mount %s", m.Dest)
|
|
||||||
}
|
|
||||||
mounts, release, err := mountable.Mount()
|
|
||||||
if err != nil {
|
|
||||||
releaseAll()
|
|
||||||
return nil, nil, errors.WithStack(err)
|
|
||||||
}
|
|
||||||
releasers = append(releasers, release)
|
|
||||||
for _, mount := range mounts {
|
|
||||||
mount, err = sm.subMount(mount, m.Selector)
|
|
||||||
if err != nil {
|
|
||||||
releaseAll()
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
s.Mounts = append(s.Mounts, specs.Mount{
|
|
||||||
Destination: m.Dest,
|
|
||||||
Type: mount.Type,
|
|
||||||
Source: mount.Source,
|
|
||||||
Options: mount.Options,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s, releaseAll, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type mountRef struct {
|
// generateSecurityOpts may affect mounts, so must be called after generateMountOpts
|
||||||
mount mount.Mount
|
func generateSecurityOpts(mode pb.SecurityMode) ([]oci.SpecOpts, error) {
|
||||||
unmount func() error
|
if mode == pb.SecurityMode_INSECURE {
|
||||||
|
return []oci.SpecOpts{
|
||||||
|
security.WithInsecureSpec(),
|
||||||
|
oci.WithWriteableCgroupfs,
|
||||||
|
oci.WithWriteableSysfs,
|
||||||
|
}, nil
|
||||||
|
} else if system.SeccompSupported() && mode == pb.SecurityMode_SANDBOX {
|
||||||
|
return []oci.SpecOpts{seccomp.WithDefaultProfile()}, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type submounts struct {
|
// generateProcessModeOpts may affect mounts, so must be called after generateMountOpts
|
||||||
m map[uint64]mountRef
|
func generateProcessModeOpts(mode ProcessMode) ([]oci.SpecOpts, error) {
|
||||||
|
if mode == NoProcessSandbox {
|
||||||
|
return []oci.SpecOpts{
|
||||||
|
oci.WithHostNamespace(specs.PIDNamespace),
|
||||||
|
withBoundProc(),
|
||||||
|
}, nil
|
||||||
|
// TODO(AkihiroSuda): Configure seccomp to disable ptrace (and prctl?) explicitly
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *submounts) subMount(m mount.Mount, subPath string) (mount.Mount, error) {
|
func generateIDmapOpts(idmap *idtools.IdentityMapping) ([]oci.SpecOpts, error) {
|
||||||
if path.Join("/", subPath) == "/" {
|
if idmap == nil {
|
||||||
return m, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
if s.m == nil {
|
return []oci.SpecOpts{
|
||||||
s.m = map[uint64]mountRef{}
|
oci.WithUserNamespace(specMapping(idmap.UIDs()), specMapping(idmap.GIDs())),
|
||||||
}
|
}, nil
|
||||||
h, err := hashstructure.Hash(m, nil)
|
|
||||||
if err != nil {
|
|
||||||
return mount.Mount{}, nil
|
|
||||||
}
|
|
||||||
if mr, ok := s.m[h]; ok {
|
|
||||||
sm, err := sub(mr.mount, subPath)
|
|
||||||
if err != nil {
|
|
||||||
return mount.Mount{}, nil
|
|
||||||
}
|
|
||||||
return sm, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
lm := snapshot.LocalMounterWithMounts([]mount.Mount{m})
|
|
||||||
|
|
||||||
mp, err := lm.Mount()
|
|
||||||
if err != nil {
|
|
||||||
return mount.Mount{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
opts := []string{"rbind"}
|
|
||||||
for _, opt := range m.Options {
|
|
||||||
if opt == "ro" {
|
|
||||||
opts = append(opts, opt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s.m[h] = mountRef{
|
|
||||||
mount: mount.Mount{
|
|
||||||
Source: mp,
|
|
||||||
Type: "bind",
|
|
||||||
Options: opts,
|
|
||||||
},
|
|
||||||
unmount: lm.Unmount,
|
|
||||||
}
|
|
||||||
|
|
||||||
sm, err := sub(s.m[h].mount, subPath)
|
|
||||||
if err != nil {
|
|
||||||
return mount.Mount{}, err
|
|
||||||
}
|
|
||||||
return sm, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *submounts) cleanup() {
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
wg.Add(len(s.m))
|
|
||||||
for _, m := range s.m {
|
|
||||||
func(m mountRef) {
|
|
||||||
go func() {
|
|
||||||
m.unmount()
|
|
||||||
wg.Done()
|
|
||||||
}()
|
|
||||||
}(m)
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
func sub(m mount.Mount, subPath string) (mount.Mount, error) {
|
|
||||||
src, err := fs.RootPath(m.Source, subPath)
|
|
||||||
if err != nil {
|
|
||||||
return mount.Mount{}, err
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
42
vendor/github.com/moby/buildkit/executor/oci/spec_windows.go
generated
vendored
Normal file
42
vendor/github.com/moby/buildkit/executor/oci/spec_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package oci
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containerd/containerd/contrib/seccomp"
|
||||||
|
"github.com/containerd/containerd/oci"
|
||||||
|
"github.com/docker/docker/pkg/idtools"
|
||||||
|
"github.com/moby/buildkit/solver/pb"
|
||||||
|
"github.com/moby/buildkit/util/system"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func generateMountOpts(resolvConf, hostsFile string) ([]oci.SpecOpts, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateSecurityOpts may affect mounts, so must be called after generateMountOpts
|
||||||
|
func generateSecurityOpts(mode pb.SecurityMode) ([]oci.SpecOpts, error) {
|
||||||
|
if mode == pb.SecurityMode_INSECURE {
|
||||||
|
return nil, errors.New("no support for running in insecure mode on Windows")
|
||||||
|
} else if system.SeccompSupported() && mode == pb.SecurityMode_SANDBOX {
|
||||||
|
// TODO: Can LCOW support seccomp? Does that even make sense?
|
||||||
|
return []oci.SpecOpts{seccomp.WithDefaultProfile()}, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateProcessModeOpts may affect mounts, so must be called after generateMountOpts
|
||||||
|
func generateProcessModeOpts(mode ProcessMode) ([]oci.SpecOpts, error) {
|
||||||
|
if mode == NoProcessSandbox {
|
||||||
|
return nil, errors.New("no support for NoProcessSandbox on Windows")
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateIDmapOpts(idmap *idtools.IdentityMapping) ([]oci.SpecOpts, error) {
|
||||||
|
if idmap == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("no support for IdentityMapping on Windows")
|
||||||
|
}
|
2
vendor/github.com/moby/buildkit/executor/oci/user.go
generated
vendored
2
vendor/github.com/moby/buildkit/executor/oci/user.go
generated
vendored
|
@ -14,7 +14,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetUser(ctx context.Context, root, username string) (uint32, uint32, []uint32, error) {
|
func GetUser(root, username string) (uint32, uint32, []uint32, error) {
|
||||||
// fast path from uid/gid
|
// fast path from uid/gid
|
||||||
if uid, gid, err := ParseUIDGID(username); err == nil {
|
if uid, gid, err := ParseUIDGID(username); err == nil {
|
||||||
return uid, gid, nil, nil
|
return uid, gid, nil, nil
|
||||||
|
|
57
vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go
generated
vendored
57
vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go
generated
vendored
|
@ -12,15 +12,16 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
containerdoci "github.com/containerd/containerd/oci"
|
containerdoci "github.com/containerd/containerd/oci"
|
||||||
"github.com/containerd/continuity/fs"
|
"github.com/containerd/continuity/fs"
|
||||||
runc "github.com/containerd/go-runc"
|
runc "github.com/containerd/go-runc"
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
"github.com/moby/buildkit/cache"
|
|
||||||
"github.com/moby/buildkit/executor"
|
"github.com/moby/buildkit/executor"
|
||||||
"github.com/moby/buildkit/executor/oci"
|
"github.com/moby/buildkit/executor/oci"
|
||||||
"github.com/moby/buildkit/identity"
|
"github.com/moby/buildkit/identity"
|
||||||
|
"github.com/moby/buildkit/solver/errdefs"
|
||||||
"github.com/moby/buildkit/solver/pb"
|
"github.com/moby/buildkit/solver/pb"
|
||||||
"github.com/moby/buildkit/util/network"
|
"github.com/moby/buildkit/util/network"
|
||||||
rootlessspecconv "github.com/moby/buildkit/util/rootless/specconv"
|
rootlessspecconv "github.com/moby/buildkit/util/rootless/specconv"
|
||||||
|
@ -52,7 +53,6 @@ var defaultCommandCandidates = []string{"buildkit-runc", "runc"}
|
||||||
type runcExecutor struct {
|
type runcExecutor struct {
|
||||||
runc *runc.Runc
|
runc *runc.Runc
|
||||||
root string
|
root string
|
||||||
cmd string
|
|
||||||
cgroupParent string
|
cgroupParent string
|
||||||
rootless bool
|
rootless bool
|
||||||
networkProviders map[pb.NetMode]network.Provider
|
networkProviders map[pb.NetMode]network.Provider
|
||||||
|
@ -106,12 +106,13 @@ func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Ex
|
||||||
Command: cmd,
|
Command: cmd,
|
||||||
Log: filepath.Join(root, "runc-log.json"),
|
Log: filepath.Join(root, "runc-log.json"),
|
||||||
LogFormat: runc.JSON,
|
LogFormat: runc.JSON,
|
||||||
PdeathSignal: syscall.SIGKILL, // this can still leak the process
|
|
||||||
Setpgid: true,
|
Setpgid: true,
|
||||||
// we don't execute runc with --rootless=(true|false) explicitly,
|
// we don't execute runc with --rootless=(true|false) explicitly,
|
||||||
// so as to support non-runc runtimes
|
// so as to support non-runc runtimes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateRuncFieldsForHostOS(runtime)
|
||||||
|
|
||||||
w := &runcExecutor{
|
w := &runcExecutor{
|
||||||
runc: runtime,
|
runc: runtime,
|
||||||
root: root,
|
root: root,
|
||||||
|
@ -128,7 +129,7 @@ func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Ex
|
||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *runcExecutor) Run(ctx context.Context, id string, root cache.Mountable, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (err error) {
|
func (w *runcExecutor) Run(ctx context.Context, id string, root executor.Mount, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (err error) {
|
||||||
meta := process.Meta
|
meta := process.Meta
|
||||||
|
|
||||||
startedOnce := sync.Once{}
|
startedOnce := sync.Once{}
|
||||||
|
@ -168,7 +169,7 @@ func (w *runcExecutor) Run(ctx context.Context, id string, root cache.Mountable,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
hostsFile, clean, err := oci.GetHostsFile(ctx, w.root, meta.ExtraHosts, w.idmap)
|
hostsFile, clean, err := oci.GetHostsFile(ctx, w.root, meta.ExtraHosts, w.idmap, meta.Hostname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -176,7 +177,7 @@ func (w *runcExecutor) Run(ctx context.Context, id string, root cache.Mountable,
|
||||||
defer clean()
|
defer clean()
|
||||||
}
|
}
|
||||||
|
|
||||||
mountable, err := root.Mount(ctx, false)
|
mountable, err := root.Src.Mount(ctx, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -213,7 +214,9 @@ func (w *runcExecutor) Run(ctx context.Context, id string, root cache.Mountable,
|
||||||
}
|
}
|
||||||
defer mount.Unmount(rootFSPath, 0)
|
defer mount.Unmount(rootFSPath, 0)
|
||||||
|
|
||||||
uid, gid, sgids, err := oci.GetUser(ctx, rootFSPath, meta.User)
|
defer executor.MountStubsCleaner(rootFSPath, mounts)()
|
||||||
|
|
||||||
|
uid, gid, sgids, err := oci.GetUser(rootFSPath, meta.User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -258,7 +261,7 @@ func (w *runcExecutor) Run(ctx context.Context, id string, root cache.Mountable,
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
spec.Root.Path = rootFSPath
|
spec.Root.Path = rootFSPath
|
||||||
if _, ok := root.(cache.ImmutableRef); ok { // TODO: pass in with mount, not ref type
|
if root.Readonly {
|
||||||
spec.Root.Readonly = true
|
spec.Root.Readonly = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,28 +326,37 @@ func (w *runcExecutor) Run(ctx context.Context, id string, root cache.Mountable,
|
||||||
close(started)
|
close(started)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
status, err := w.runc.Run(runCtx, id, bundle, &runc.CreateOpts{
|
|
||||||
IO: &forwardIO{stdin: process.Stdin, stdout: process.Stdout, stderr: process.Stderr},
|
|
||||||
NoPivot: w.noPivot,
|
|
||||||
})
|
|
||||||
close(ended)
|
|
||||||
|
|
||||||
if status != 0 || err != nil {
|
err = w.run(runCtx, id, bundle, process)
|
||||||
if err == nil {
|
close(ended)
|
||||||
err = errors.Errorf("exit code: %d", status)
|
return exitError(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func exitError(ctx context.Context, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
exitErr := &errdefs.ExitError{
|
||||||
|
ExitCode: containerd.UnknownExitStatus,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
var runcExitError *runc.ExitError
|
||||||
|
if errors.As(err, &runcExitError) {
|
||||||
|
exitErr = &errdefs.ExitError{
|
||||||
|
ExitCode: uint32(runcExitError.Status),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return errors.Wrapf(ctx.Err(), err.Error())
|
exitErr.Err = errors.Wrapf(ctx.Err(), exitErr.Error())
|
||||||
|
return exitErr
|
||||||
default:
|
default:
|
||||||
return stack.Enable(err)
|
return stack.Enable(exitErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *runcExecutor) Exec(ctx context.Context, id string, process executor.ProcessInfo) error {
|
func (w *runcExecutor) Exec(ctx context.Context, id string, process executor.ProcessInfo) (err error) {
|
||||||
// first verify the container is running, if we get an error assume the container
|
// first verify the container is running, if we get an error assume the container
|
||||||
// is in the process of being created and check again every 100ms or until
|
// is in the process of being created and check again every 100ms or until
|
||||||
// context is canceled.
|
// context is canceled.
|
||||||
|
@ -386,7 +398,7 @@ func (w *runcExecutor) Exec(ctx context.Context, id string, process executor.Pro
|
||||||
}
|
}
|
||||||
|
|
||||||
if process.Meta.User != "" {
|
if process.Meta.User != "" {
|
||||||
uid, gid, sgids, err := oci.GetUser(ctx, state.Rootfs, process.Meta.User)
|
uid, gid, sgids, err := oci.GetUser(state.Rootfs, process.Meta.User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -407,9 +419,8 @@ func (w *runcExecutor) Exec(ctx context.Context, id string, process executor.Pro
|
||||||
spec.Process.Env = process.Meta.Env
|
spec.Process.Env = process.Meta.Env
|
||||||
}
|
}
|
||||||
|
|
||||||
return w.runc.Exec(ctx, id, *spec.Process, &runc.ExecOpts{
|
err = w.exec(ctx, id, state.Bundle, spec.Process, process)
|
||||||
IO: &forwardIO{stdin: process.Stdin, stdout: process.Stdout, stderr: process.Stderr},
|
return exitError(ctx, err)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type forwardIO struct {
|
type forwardIO struct {
|
||||||
|
|
36
vendor/github.com/moby/buildkit/executor/runcexecutor/executor_common.go
generated
vendored
Normal file
36
vendor/github.com/moby/buildkit/executor/runcexecutor/executor_common.go
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package runcexecutor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
runc "github.com/containerd/go-runc"
|
||||||
|
"github.com/moby/buildkit/executor"
|
||||||
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var unsupportedConsoleError = errors.New("tty for runc is only supported on linux")
|
||||||
|
|
||||||
|
func updateRuncFieldsForHostOS(runtime *runc.Runc) {}
|
||||||
|
|
||||||
|
func (w *runcExecutor) run(ctx context.Context, id, bundle string, process executor.ProcessInfo) error {
|
||||||
|
if process.Meta.Tty {
|
||||||
|
return unsupportedConsoleError
|
||||||
|
}
|
||||||
|
_, err := w.runc.Run(ctx, id, bundle, &runc.CreateOpts{
|
||||||
|
IO: &forwardIO{stdin: process.Stdin, stdout: process.Stdout, stderr: process.Stderr},
|
||||||
|
NoPivot: w.noPivot,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *runcExecutor) exec(ctx context.Context, id, bundle string, specsProcess *specs.Process, process executor.ProcessInfo) error {
|
||||||
|
if process.Meta.Tty {
|
||||||
|
return unsupportedConsoleError
|
||||||
|
}
|
||||||
|
return w.runc.Exec(ctx, id, *specsProcess, &runc.ExecOpts{
|
||||||
|
IO: &forwardIO{stdin: process.Stdin, stdout: process.Stdout, stderr: process.Stderr},
|
||||||
|
})
|
||||||
|
}
|
160
vendor/github.com/moby/buildkit/executor/runcexecutor/executor_linux.go
generated
vendored
Normal file
160
vendor/github.com/moby/buildkit/executor/runcexecutor/executor_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
package runcexecutor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containerd/console"
|
||||||
|
runc "github.com/containerd/go-runc"
|
||||||
|
"github.com/docker/docker/pkg/signal"
|
||||||
|
"github.com/moby/buildkit/executor"
|
||||||
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
|
func updateRuncFieldsForHostOS(runtime *runc.Runc) {
|
||||||
|
// PdeathSignal only supported on unix platforms
|
||||||
|
runtime.PdeathSignal = syscall.SIGKILL // this can still leak the process
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *runcExecutor) run(ctx context.Context, id, bundle string, process executor.ProcessInfo) error {
|
||||||
|
return w.callWithIO(ctx, id, bundle, process, func(ctx context.Context, started chan<- int, io runc.IO) error {
|
||||||
|
_, err := w.runc.Run(ctx, id, bundle, &runc.CreateOpts{
|
||||||
|
NoPivot: w.noPivot,
|
||||||
|
Started: started,
|
||||||
|
IO: io,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *runcExecutor) exec(ctx context.Context, id, bundle string, specsProcess *specs.Process, process executor.ProcessInfo) error {
|
||||||
|
return w.callWithIO(ctx, id, bundle, process, func(ctx context.Context, started chan<- int, io runc.IO) error {
|
||||||
|
return w.runc.Exec(ctx, id, *specsProcess, &runc.ExecOpts{
|
||||||
|
Started: started,
|
||||||
|
IO: io,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type runcCall func(ctx context.Context, started chan<- int, io runc.IO) error
|
||||||
|
|
||||||
|
func (w *runcExecutor) callWithIO(ctx context.Context, id, bundle string, process executor.ProcessInfo, call runcCall) error {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
if !process.Meta.Tty {
|
||||||
|
return call(ctx, nil, &forwardIO{stdin: process.Stdin, stdout: process.Stdout, stderr: process.Stderr})
|
||||||
|
}
|
||||||
|
|
||||||
|
ptm, ptsName, err := console.NewPty()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pts, err := os.OpenFile(ptsName, os.O_RDWR|syscall.O_NOCTTY, 0)
|
||||||
|
if err != nil {
|
||||||
|
ptm.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
eg, ctx := errgroup.WithContext(ctx)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if process.Stdin != nil {
|
||||||
|
process.Stdin.Close()
|
||||||
|
}
|
||||||
|
pts.Close()
|
||||||
|
ptm.Close()
|
||||||
|
cancel() // this will shutdown resize loop
|
||||||
|
err := eg.Wait()
|
||||||
|
if err != nil {
|
||||||
|
logrus.Warningf("error while shutting down tty io: %s", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if process.Stdin != nil {
|
||||||
|
eg.Go(func() error {
|
||||||
|
_, err := io.Copy(ptm, process.Stdin)
|
||||||
|
// stdin might be a pipe, so this is like EOF
|
||||||
|
if errors.Is(err, io.ErrClosedPipe) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if process.Stdout != nil {
|
||||||
|
eg.Go(func() error {
|
||||||
|
_, err := io.Copy(process.Stdout, ptm)
|
||||||
|
// ignore `read /dev/ptmx: input/output error` when ptm is closed
|
||||||
|
var ptmClosedError *os.PathError
|
||||||
|
if errors.As(err, &ptmClosedError) {
|
||||||
|
if ptmClosedError.Op == "read" &&
|
||||||
|
ptmClosedError.Path == "/dev/ptmx" &&
|
||||||
|
ptmClosedError.Err == syscall.EIO {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
started := make(chan int, 1)
|
||||||
|
|
||||||
|
eg.Go(func() error {
|
||||||
|
startedCtx, timeout := context.WithTimeout(ctx, 10*time.Second)
|
||||||
|
defer timeout()
|
||||||
|
var runcProcess *os.Process
|
||||||
|
select {
|
||||||
|
case <-startedCtx.Done():
|
||||||
|
return errors.New("runc started message never received")
|
||||||
|
case pid, ok := <-started:
|
||||||
|
if !ok {
|
||||||
|
return errors.New("runc process failed to send pid")
|
||||||
|
}
|
||||||
|
runcProcess, err = os.FindProcess(pid)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "unable to find runc process for pid %d", pid)
|
||||||
|
}
|
||||||
|
defer runcProcess.Release()
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil
|
||||||
|
case resize := <-process.Resize:
|
||||||
|
err = ptm.Resize(console.WinSize{
|
||||||
|
Height: uint16(resize.Rows),
|
||||||
|
Width: uint16(resize.Cols),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("failed to resize ptm: %s", err)
|
||||||
|
}
|
||||||
|
err = runcProcess.Signal(signal.SIGWINCH)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("failed to send SIGWINCH to process: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
runcIO := &forwardIO{}
|
||||||
|
if process.Stdin != nil {
|
||||||
|
runcIO.stdin = pts
|
||||||
|
}
|
||||||
|
if process.Stdout != nil {
|
||||||
|
runcIO.stdout = pts
|
||||||
|
}
|
||||||
|
if process.Stderr != nil {
|
||||||
|
runcIO.stderr = pts
|
||||||
|
}
|
||||||
|
|
||||||
|
return call(ctx, started, runcIO)
|
||||||
|
}
|
49
vendor/github.com/moby/buildkit/executor/stubs.go
generated
vendored
Normal file
49
vendor/github.com/moby/buildkit/executor/stubs.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package executor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/containerd/continuity/fs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func MountStubsCleaner(dir string, mounts []Mount) func() {
|
||||||
|
names := []string{"/etc/resolv.conf", "/etc/hosts"}
|
||||||
|
|
||||||
|
for _, m := range mounts {
|
||||||
|
names = append(names, m.Dest)
|
||||||
|
}
|
||||||
|
|
||||||
|
paths := make([]string, 0, len(names))
|
||||||
|
|
||||||
|
for _, p := range names {
|
||||||
|
p = filepath.Join("/", p)
|
||||||
|
if p == "/" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
realPath, err := fs.RootPath(dir, p)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = os.Lstat(realPath)
|
||||||
|
if errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) {
|
||||||
|
paths = append(paths, realPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return func() {
|
||||||
|
for _, p := range paths {
|
||||||
|
st, err := os.Lstat(p)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if st.Size() != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
os.Remove(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/types.go
generated
vendored
7
vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/types.go
generated
vendored
|
@ -1,11 +1,16 @@
|
||||||
package exptypes
|
package exptypes
|
||||||
|
|
||||||
import specs "github.com/opencontainers/image-spec/specs-go/v1"
|
import (
|
||||||
|
"github.com/opencontainers/go-digest"
|
||||||
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
)
|
||||||
|
|
||||||
const ExporterImageConfigKey = "containerimage.config"
|
const ExporterImageConfigKey = "containerimage.config"
|
||||||
const ExporterInlineCache = "containerimage.inlinecache"
|
const ExporterInlineCache = "containerimage.inlinecache"
|
||||||
const ExporterPlatformsKey = "refs.platforms"
|
const ExporterPlatformsKey = "refs.platforms"
|
||||||
|
|
||||||
|
const EmptyGZLayer = digest.Digest("sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1")
|
||||||
|
|
||||||
type Platforms struct {
|
type Platforms struct {
|
||||||
Platforms []Platform
|
Platforms []Platform
|
||||||
}
|
}
|
||||||
|
|
4
vendor/github.com/moby/buildkit/exporter/local/export.go
generated
vendored
4
vendor/github.com/moby/buildkit/exporter/local/export.go
generated
vendored
|
@ -51,7 +51,7 @@ func (e *localExporterInstance) Export(ctx context.Context, inp exporter.Source,
|
||||||
timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
caller, err := e.opt.SessionManager.Get(timeoutCtx, sessionID)
|
caller, err := e.opt.SessionManager.Get(timeoutCtx, sessionID, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ func (e *localExporterInstance) Export(ctx context.Context, inp exporter.Source,
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(src)
|
defer os.RemoveAll(src)
|
||||||
} else {
|
} else {
|
||||||
mount, err := ref.Mount(ctx, true)
|
mount, err := ref.Mount(ctx, true, session.NewGroup(sessionID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
4
vendor/github.com/moby/buildkit/exporter/tar/export.go
generated
vendored
4
vendor/github.com/moby/buildkit/exporter/tar/export.go
generated
vendored
|
@ -65,7 +65,7 @@ func (e *localExporterInstance) Export(ctx context.Context, inp exporter.Source,
|
||||||
}
|
}
|
||||||
defers = append(defers, func() { os.RemoveAll(src) })
|
defers = append(defers, func() { os.RemoveAll(src) })
|
||||||
} else {
|
} else {
|
||||||
mount, err := ref.Mount(ctx, true)
|
mount, err := ref.Mount(ctx, true, session.NewGroup(sessionID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ func (e *localExporterInstance) Export(ctx context.Context, inp exporter.Source,
|
||||||
timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
caller, err := e.opt.SessionManager.Get(timeoutCtx, sessionID)
|
caller, err := e.opt.SessionManager.Get(timeoutCtx, sessionID, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
32
vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go
generated
vendored
32
vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go
generated
vendored
|
@ -14,11 +14,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containerd/containerd/platforms"
|
"github.com/containerd/containerd/platforms"
|
||||||
"github.com/docker/docker/builder/dockerignore"
|
|
||||||
controlapi "github.com/moby/buildkit/api/services/control"
|
controlapi "github.com/moby/buildkit/api/services/control"
|
||||||
"github.com/moby/buildkit/client/llb"
|
"github.com/moby/buildkit/client/llb"
|
||||||
"github.com/moby/buildkit/exporter/containerimage/exptypes"
|
"github.com/moby/buildkit/exporter/containerimage/exptypes"
|
||||||
"github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb"
|
"github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb"
|
||||||
|
"github.com/moby/buildkit/frontend/dockerfile/dockerignore"
|
||||||
"github.com/moby/buildkit/frontend/dockerfile/parser"
|
"github.com/moby/buildkit/frontend/dockerfile/parser"
|
||||||
"github.com/moby/buildkit/frontend/gateway/client"
|
"github.com/moby/buildkit/frontend/gateway/client"
|
||||||
gwpb "github.com/moby/buildkit/frontend/gateway/pb"
|
gwpb "github.com/moby/buildkit/frontend/gateway/pb"
|
||||||
|
@ -53,16 +53,23 @@ const (
|
||||||
keyNameDockerfile = "dockerfilekey"
|
keyNameDockerfile = "dockerfilekey"
|
||||||
keyContextSubDir = "contextsubdir"
|
keyContextSubDir = "contextsubdir"
|
||||||
keyContextKeepGitDir = "build-arg:BUILDKIT_CONTEXT_KEEP_GIT_DIR"
|
keyContextKeepGitDir = "build-arg:BUILDKIT_CONTEXT_KEEP_GIT_DIR"
|
||||||
|
keySyntax = "build-arg:BUILDKIT_SYNTAX"
|
||||||
|
keyHostname = "hostname"
|
||||||
)
|
)
|
||||||
|
|
||||||
var httpPrefix = regexp.MustCompile(`^https?://`)
|
var httpPrefix = regexp.MustCompile(`^https?://`)
|
||||||
var gitUrlPathWithFragmentSuffix = regexp.MustCompile(`\.git(?:#.+)?$`)
|
var gitURLPathWithFragmentSuffix = regexp.MustCompile(`\.git(?:#.+)?$`)
|
||||||
|
|
||||||
func Build(ctx context.Context, c client.Client) (*client.Result, error) {
|
func Build(ctx context.Context, c client.Client) (*client.Result, error) {
|
||||||
opts := c.BuildOpts().Opts
|
opts := c.BuildOpts().Opts
|
||||||
caps := c.BuildOpts().LLBCaps
|
caps := c.BuildOpts().LLBCaps
|
||||||
gwcaps := c.BuildOpts().Caps
|
gwcaps := c.BuildOpts().Caps
|
||||||
|
|
||||||
|
allowForward, capsError := validateCaps(opts["frontend.caps"])
|
||||||
|
if !allowForward && capsError != nil {
|
||||||
|
return nil, capsError
|
||||||
|
}
|
||||||
|
|
||||||
marshalOpts := []llb.ConstraintsOpt{llb.WithCaps(caps)}
|
marshalOpts := []llb.ConstraintsOpt{llb.WithCaps(caps)}
|
||||||
|
|
||||||
localNameContext := DefaultLocalNameContext
|
localNameContext := DefaultLocalNameContext
|
||||||
|
@ -317,8 +324,14 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := opts["cmdline"]; !ok {
|
if _, ok := opts["cmdline"]; !ok {
|
||||||
ref, cmdline, loc, ok := dockerfile2llb.DetectSyntax(bytes.NewBuffer(dtDockerfile))
|
if cmdline, ok := opts[keySyntax]; ok {
|
||||||
if ok {
|
p := strings.SplitN(strings.TrimSpace(cmdline), " ", 2)
|
||||||
|
res, err := forwardGateway(ctx, c, p[0], cmdline)
|
||||||
|
if err != nil && len(errdefs.Sources(err)) == 0 {
|
||||||
|
return nil, errors.Wrapf(err, "failed with %s = %s", keySyntax, cmdline)
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
} else if ref, cmdline, loc, ok := dockerfile2llb.DetectSyntax(bytes.NewBuffer(dtDockerfile)); ok {
|
||||||
res, err := forwardGateway(ctx, c, ref, cmdline)
|
res, err := forwardGateway(ctx, c, ref, cmdline)
|
||||||
if err != nil && len(errdefs.Sources(err)) == 0 {
|
if err != nil && len(errdefs.Sources(err)) == 0 {
|
||||||
return nil, wrapSource(err, sourceMap, loc)
|
return nil, wrapSource(err, sourceMap, loc)
|
||||||
|
@ -327,6 +340,14 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if capsError != nil {
|
||||||
|
return nil, capsError
|
||||||
|
}
|
||||||
|
|
||||||
|
if res, ok, err := checkSubRequest(ctx, opts); ok {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
exportMap := len(targetPlatforms) > 1
|
exportMap := len(targetPlatforms) > 1
|
||||||
|
|
||||||
if v := opts[keyMultiPlatform]; v != "" {
|
if v := opts[keyMultiPlatform]; v != "" {
|
||||||
|
@ -375,6 +396,7 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
|
||||||
OverrideCopyImage: opts[keyOverrideCopyImage],
|
OverrideCopyImage: opts[keyOverrideCopyImage],
|
||||||
LLBCaps: &caps,
|
LLBCaps: &caps,
|
||||||
SourceMap: sourceMap,
|
SourceMap: sourceMap,
|
||||||
|
Hostname: opts[keyHostname],
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -512,7 +534,7 @@ func filter(opt map[string]string, key string) map[string]string {
|
||||||
|
|
||||||
func detectGitContext(ref, gitContext string) (*llb.State, bool) {
|
func detectGitContext(ref, gitContext string) (*llb.State, bool) {
|
||||||
found := false
|
found := false
|
||||||
if httpPrefix.MatchString(ref) && gitUrlPathWithFragmentSuffix.MatchString(ref) {
|
if httpPrefix.MatchString(ref) && gitURLPathWithFragmentSuffix.MatchString(ref) {
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
34
vendor/github.com/moby/buildkit/frontend/dockerfile/builder/caps.go
generated
vendored
Normal file
34
vendor/github.com/moby/buildkit/frontend/dockerfile/builder/caps.go
generated
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package builder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/moby/buildkit/solver/errdefs"
|
||||||
|
"github.com/moby/buildkit/util/grpcerrors"
|
||||||
|
"github.com/moby/buildkit/util/stack"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
)
|
||||||
|
|
||||||
|
var enabledCaps = map[string]struct{}{
|
||||||
|
"moby.buildkit.frontend.inputs": {},
|
||||||
|
"moby.buildkit.frontend.subrequests": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateCaps(req string) (forward bool, err error) {
|
||||||
|
if req == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
caps := strings.Split(req, ",")
|
||||||
|
for _, c := range caps {
|
||||||
|
parts := strings.SplitN(c, "+", 2)
|
||||||
|
if _, ok := enabledCaps[parts[0]]; !ok {
|
||||||
|
err = stack.Enable(grpcerrors.WrapCode(errdefs.NewUnsupportedFrontendCapError(parts[0]), codes.Unimplemented))
|
||||||
|
if strings.Contains(c, "+forward") {
|
||||||
|
forward = true
|
||||||
|
} else {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
39
vendor/github.com/moby/buildkit/frontend/dockerfile/builder/subrequests.go
generated
vendored
Normal file
39
vendor/github.com/moby/buildkit/frontend/dockerfile/builder/subrequests.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package builder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/moby/buildkit/frontend/gateway/client"
|
||||||
|
"github.com/moby/buildkit/frontend/subrequests"
|
||||||
|
"github.com/moby/buildkit/solver/errdefs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func checkSubRequest(ctx context.Context, opts map[string]string) (*client.Result, bool, error) {
|
||||||
|
req, ok := opts["requestid"]
|
||||||
|
if !ok {
|
||||||
|
return nil, false, nil
|
||||||
|
}
|
||||||
|
switch req {
|
||||||
|
case subrequests.RequestSubrequestsDescribe:
|
||||||
|
res, err := describe()
|
||||||
|
return res, true, err
|
||||||
|
default:
|
||||||
|
return nil, true, errdefs.NewUnsupportedSubrequestError(req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func describe() (*client.Result, error) {
|
||||||
|
all := []subrequests.Request{
|
||||||
|
subrequests.SubrequestsDescribeDefinition,
|
||||||
|
}
|
||||||
|
dt, err := json.MarshalIndent(all, " ", "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := client.NewResult()
|
||||||
|
res.Metadata = map[string][]byte{
|
||||||
|
"result.json": dt,
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
38
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go
generated
vendored
38
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go
generated
vendored
|
@ -62,6 +62,7 @@ type ConvertOpt struct {
|
||||||
LLBCaps *apicaps.CapSet
|
LLBCaps *apicaps.CapSet
|
||||||
ContextLocalName string
|
ContextLocalName string
|
||||||
SourceMap *llb.SourceMap
|
SourceMap *llb.SourceMap
|
||||||
|
Hostname string
|
||||||
}
|
}
|
||||||
|
|
||||||
func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, *Image, error) {
|
func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, *Image, error) {
|
||||||
|
@ -94,11 +95,13 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
|
||||||
|
|
||||||
shlex := shell.NewLex(dockerfile.EscapeToken)
|
shlex := shell.NewLex(dockerfile.EscapeToken)
|
||||||
|
|
||||||
for _, metaArg := range metaArgs {
|
for _, cmd := range metaArgs {
|
||||||
|
for _, metaArg := range cmd.Args {
|
||||||
if metaArg.Value != nil {
|
if metaArg.Value != nil {
|
||||||
*metaArg.Value, _ = shlex.ProcessWordWithMap(*metaArg.Value, metaArgsToMap(optMetaArgs))
|
*metaArg.Value, _ = shlex.ProcessWordWithMap(*metaArg.Value, metaArgsToMap(optMetaArgs))
|
||||||
}
|
}
|
||||||
optMetaArgs = append(optMetaArgs, setKVValue(metaArg.KeyValuePairOptional, opt.BuildArgs))
|
optMetaArgs = append(optMetaArgs, setKVValue(metaArg, opt.BuildArgs))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
metaResolver := opt.MetaResolver
|
metaResolver := opt.MetaResolver
|
||||||
|
@ -314,7 +317,11 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
|
||||||
|
|
||||||
// make sure that PATH is always set
|
// make sure that PATH is always set
|
||||||
if _, ok := shell.BuildEnvs(d.image.Config.Env)["PATH"]; !ok {
|
if _, ok := shell.BuildEnvs(d.image.Config.Env)["PATH"]; !ok {
|
||||||
d.image.Config.Env = append(d.image.Config.Env, "PATH="+system.DefaultPathEnv)
|
var os string
|
||||||
|
if d.platform != nil {
|
||||||
|
os = d.platform.OS
|
||||||
|
}
|
||||||
|
d.image.Config.Env = append(d.image.Config.Env, "PATH="+system.DefaultPathEnv(os))
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize base metadata from image conf
|
// initialize base metadata from image conf
|
||||||
|
@ -322,6 +329,9 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
|
||||||
k, v := parseKeyValue(env)
|
k, v := parseKeyValue(env)
|
||||||
d.state = d.state.AddEnv(k, v)
|
d.state = d.state.AddEnv(k, v)
|
||||||
}
|
}
|
||||||
|
if opt.Hostname != "" {
|
||||||
|
d.state = d.state.Hostname(opt.Hostname)
|
||||||
|
}
|
||||||
if d.image.Config.WorkingDir != "" {
|
if d.image.Config.WorkingDir != "" {
|
||||||
if err = dispatchWorkdir(d, &instructions.WorkdirCommand{Path: d.image.Config.WorkingDir}, false, nil); err != nil {
|
if err = dispatchWorkdir(d, &instructions.WorkdirCommand{Path: d.image.Config.WorkingDir}, false, nil); err != nil {
|
||||||
return nil, nil, parser.WithLocation(err, d.stage.Location)
|
return nil, nil, parser.WithLocation(err, d.stage.Location)
|
||||||
|
@ -1072,12 +1082,15 @@ func dispatchShell(d *dispatchState, c *instructions.ShellCommand) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func dispatchArg(d *dispatchState, c *instructions.ArgCommand, metaArgs []instructions.KeyValuePairOptional, buildArgValues map[string]string) error {
|
func dispatchArg(d *dispatchState, c *instructions.ArgCommand, metaArgs []instructions.KeyValuePairOptional, buildArgValues map[string]string) error {
|
||||||
commitStr := "ARG " + c.Key
|
commitStrs := make([]string, 0, len(c.Args))
|
||||||
buildArg := setKVValue(c.KeyValuePairOptional, buildArgValues)
|
for _, arg := range c.Args {
|
||||||
|
buildArg := setKVValue(arg, buildArgValues)
|
||||||
|
|
||||||
if c.Value != nil {
|
commitStr := arg.Key
|
||||||
commitStr += "=" + *c.Value
|
if arg.Value != nil {
|
||||||
|
commitStr += "=" + *arg.Value
|
||||||
}
|
}
|
||||||
|
commitStrs = append(commitStrs, commitStr)
|
||||||
if buildArg.Value == nil {
|
if buildArg.Value == nil {
|
||||||
for _, ma := range metaArgs {
|
for _, ma := range metaArgs {
|
||||||
if ma.Key == buildArg.Key {
|
if ma.Key == buildArg.Key {
|
||||||
|
@ -1091,7 +1104,8 @@ func dispatchArg(d *dispatchState, c *instructions.ArgCommand, metaArgs []instru
|
||||||
}
|
}
|
||||||
|
|
||||||
d.buildArgs = append(d.buildArgs, buildArg)
|
d.buildArgs = append(d.buildArgs, buildArg)
|
||||||
return commitToHistory(&d.image, commitStr, false, nil)
|
}
|
||||||
|
return commitToHistory(&d.image, "ARG "+strings.Join(commitStrs, " "), false, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func pathRelativeToWorkingDir(s llb.State, p string) (string, error) {
|
func pathRelativeToWorkingDir(s llb.State, p string) (string, error) {
|
||||||
|
@ -1308,15 +1322,15 @@ func proxyEnvFromBuildArgs(args map[string]string) *llb.ProxyEnv {
|
||||||
isNil := true
|
isNil := true
|
||||||
for k, v := range args {
|
for k, v := range args {
|
||||||
if strings.EqualFold(k, "http_proxy") {
|
if strings.EqualFold(k, "http_proxy") {
|
||||||
pe.HttpProxy = v
|
pe.HTTPProxy = v
|
||||||
isNil = false
|
isNil = false
|
||||||
}
|
}
|
||||||
if strings.EqualFold(k, "https_proxy") {
|
if strings.EqualFold(k, "https_proxy") {
|
||||||
pe.HttpsProxy = v
|
pe.HTTPSProxy = v
|
||||||
isNil = false
|
isNil = false
|
||||||
}
|
}
|
||||||
if strings.EqualFold(k, "ftp_proxy") {
|
if strings.EqualFold(k, "ftp_proxy") {
|
||||||
pe.FtpProxy = v
|
pe.FTPProxy = v
|
||||||
isNil = false
|
isNil = false
|
||||||
}
|
}
|
||||||
if strings.EqualFold(k, "no_proxy") {
|
if strings.EqualFold(k, "no_proxy") {
|
||||||
|
@ -1339,7 +1353,7 @@ func withShell(img Image, args []string) []string {
|
||||||
if len(img.Config.Shell) > 0 {
|
if len(img.Config.Shell) > 0 {
|
||||||
shell = append([]string{}, img.Config.Shell...)
|
shell = append([]string{}, img.Config.Shell...)
|
||||||
} else {
|
} else {
|
||||||
shell = defaultShell()
|
shell = defaultShell(img.OS)
|
||||||
}
|
}
|
||||||
return append(shell, strings.Join(args, " "))
|
return append(shell, strings.Join(args, " "))
|
||||||
}
|
}
|
||||||
|
|
16
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_norunmount.go
generated
vendored
16
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_norunmount.go
generated
vendored
|
@ -1,16 +0,0 @@
|
||||||
// +build !dfrunmount
|
|
||||||
|
|
||||||
package dockerfile2llb
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/moby/buildkit/client/llb"
|
|
||||||
"github.com/moby/buildkit/frontend/dockerfile/instructions"
|
|
||||||
)
|
|
||||||
|
|
||||||
func detectRunMount(cmd *command, allDispatchStates *dispatchStates) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func dispatchRunMounts(d *dispatchState, c *instructions.RunCommand, sources []*dispatchState, opt dispatchOpt) ([]llb.RunOption, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
13
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_nosecrets.go
generated
vendored
13
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_nosecrets.go
generated
vendored
|
@ -1,13 +0,0 @@
|
||||||
// +build dfrunmount,!dfsecrets
|
|
||||||
|
|
||||||
package dockerfile2llb
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/moby/buildkit/client/llb"
|
|
||||||
"github.com/moby/buildkit/frontend/dockerfile/instructions"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
func dispatchSecret(m *instructions.Mount) (llb.RunOption, error) {
|
|
||||||
return nil, errors.Errorf("secret mounts not allowed")
|
|
||||||
}
|
|
13
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_nossh.go
generated
vendored
13
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_nossh.go
generated
vendored
|
@ -1,13 +0,0 @@
|
||||||
// +build dfrunmount,!dfssh
|
|
||||||
|
|
||||||
package dockerfile2llb
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/moby/buildkit/client/llb"
|
|
||||||
"github.com/moby/buildkit/frontend/dockerfile/instructions"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
func dispatchSSH(m *instructions.Mount) (llb.RunOption, error) {
|
|
||||||
return nil, errors.Errorf("ssh mounts not allowed")
|
|
||||||
}
|
|
|
@ -1,5 +1,3 @@
|
||||||
// +build dfrunmount
|
|
||||||
|
|
||||||
package dockerfile2llb
|
package dockerfile2llb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
// +build dfsecrets
|
|
||||||
|
|
||||||
package dockerfile2llb
|
package dockerfile2llb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
2
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_ssh.go
generated
vendored
2
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_ssh.go
generated
vendored
|
@ -1,5 +1,3 @@
|
||||||
// +build dfssh
|
|
||||||
|
|
||||||
package dockerfile2llb
|
package dockerfile2llb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
8
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/defaultshell.go
generated
vendored
Normal file
8
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/defaultshell.go
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package dockerfile2llb
|
||||||
|
|
||||||
|
func defaultShell(os string) []string {
|
||||||
|
if os == "windows" {
|
||||||
|
return []string{"cmd", "/S", "/C"}
|
||||||
|
}
|
||||||
|
return []string{"/bin/sh", "-c"}
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package dockerfile2llb
|
|
||||||
|
|
||||||
func defaultShell() []string {
|
|
||||||
return []string{"/bin/sh", "-c"}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package dockerfile2llb
|
|
||||||
|
|
||||||
func defaultShell() []string {
|
|
||||||
return []string{"cmd", "/S", "/C"}
|
|
||||||
}
|
|
2
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/image.go
generated
vendored
2
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/image.go
generated
vendored
|
@ -74,6 +74,6 @@ func emptyImage(platform specs.Platform) Image {
|
||||||
}
|
}
|
||||||
img.RootFS.Type = "layers"
|
img.RootFS.Type = "layers"
|
||||||
img.Config.WorkingDir = "/"
|
img.Config.WorkingDir = "/"
|
||||||
img.Config.Env = []string{"PATH=" + system.DefaultPathEnv}
|
img.Config.Env = []string{"PATH=" + system.DefaultPathEnv(platform.OS)}
|
||||||
return img
|
return img
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package dockerignore // import "github.com/docker/docker/builder/dockerignore"
|
package dockerignore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
17
vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands.go
generated
vendored
17
vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands.go
generated
vendored
|
@ -23,6 +23,7 @@ func (kvp *KeyValuePair) String() string {
|
||||||
type KeyValuePairOptional struct {
|
type KeyValuePairOptional struct {
|
||||||
Key string
|
Key string
|
||||||
Value *string
|
Value *string
|
||||||
|
Comment string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kvpo *KeyValuePairOptional) ValueString() string {
|
func (kvpo *KeyValuePairOptional) ValueString() string {
|
||||||
|
@ -380,22 +381,25 @@ func (c *StopSignalCommand) CheckPlatform(platform string) error {
|
||||||
// Dockerfile author may optionally set a default value of this variable.
|
// Dockerfile author may optionally set a default value of this variable.
|
||||||
type ArgCommand struct {
|
type ArgCommand struct {
|
||||||
withNameAndCode
|
withNameAndCode
|
||||||
KeyValuePairOptional
|
Args []KeyValuePairOptional
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand variables
|
// Expand variables
|
||||||
func (c *ArgCommand) Expand(expander SingleWordExpander) error {
|
func (c *ArgCommand) Expand(expander SingleWordExpander) error {
|
||||||
p, err := expander(c.Key)
|
for i, v := range c.Args {
|
||||||
|
p, err := expander(v.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.Key = p
|
v.Key = p
|
||||||
if c.Value != nil {
|
if v.Value != nil {
|
||||||
p, err = expander(*c.Value)
|
p, err = expander(*v.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.Value = &p
|
v.Value = &p
|
||||||
|
}
|
||||||
|
c.Args[i] = v
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -416,6 +420,7 @@ type Stage struct {
|
||||||
SourceCode string
|
SourceCode string
|
||||||
Platform string
|
Platform string
|
||||||
Location []parser.Range
|
Location []parser.Range
|
||||||
|
Comment string
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddCommand to the stage
|
// AddCommand to the stage
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
// +build !dfsecrets
|
|
||||||
|
|
||||||
package instructions
|
|
||||||
|
|
||||||
func isSecretMountsSupported() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
7
vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_nossh.go
generated
vendored
7
vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_nossh.go
generated
vendored
|
@ -1,7 +0,0 @@
|
||||||
// +build !dfssh
|
|
||||||
|
|
||||||
package instructions
|
|
||||||
|
|
||||||
func isSSHMountsSupported() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
|
@ -1,5 +1,3 @@
|
||||||
// +build dfrunmount
|
|
||||||
|
|
||||||
package instructions
|
package instructions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue