Browse Source

Merge pull request #40814 from tonistiigi/buildkit-update

vendor: update buildkit to ae7ff174
Sebastiaan van Stijn 5 years ago
parent
commit
db669cd117
36 changed files with 1105 additions and 490 deletions
  1. 5 36
      builder/builder-next/adapters/containerimage/pull.go
  2. 3 3
      builder/builder-next/adapters/localinlinecache/inlinecache.go
  3. 2 2
      builder/builder-next/builder.go
  4. 2 2
      builder/builder-next/controller.go
  5. 1 1
      cmd/dockerd/daemon.go
  6. 35 54
      daemon/daemon.go
  7. 21 11
      registry/registry.go
  8. 2 2
      vendor.conf
  9. 5 4
      vendor/github.com/moby/buildkit/README.md
  10. 4 1
      vendor/github.com/moby/buildkit/cache/contenthash/tarsum.go
  11. 4 31
      vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go
  12. 6 0
      vendor/github.com/moby/buildkit/client/client.go
  13. 98 0
      vendor/github.com/moby/buildkit/client/llb/async.go
  14. 35 25
      vendor/github.com/moby/buildkit/client/llb/definition.go
  15. 82 81
      vendor/github.com/moby/buildkit/client/llb/exec.go
  16. 45 22
      vendor/github.com/moby/buildkit/client/llb/fileop.go
  17. 128 58
      vendor/github.com/moby/buildkit/client/llb/meta.go
  18. 9 0
      vendor/github.com/moby/buildkit/client/llb/resolver.go
  19. 37 21
      vendor/github.com/moby/buildkit/client/llb/source.go
  20. 103 65
      vendor/github.com/moby/buildkit/client/llb/state.go
  21. 9 10
      vendor/github.com/moby/buildkit/client/solve.go
  22. 105 0
      vendor/github.com/moby/buildkit/cmd/buildkitd/config/config.go
  23. 31 0
      vendor/github.com/moby/buildkit/cmd/buildkitd/config/gcpolicy.go
  24. 17 0
      vendor/github.com/moby/buildkit/cmd/buildkitd/config/gcpolicy_unix.go
  25. 7 0
      vendor/github.com/moby/buildkit/cmd/buildkitd/config/gcpolicy_windows.go
  26. 26 6
      vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go
  27. 53 13
      vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go
  28. 6 1
      vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_runmount.go
  29. 1 1
      vendor/github.com/moby/buildkit/frontend/gateway/gateway.go
  30. 3 3
      vendor/github.com/moby/buildkit/go.mod
  31. 7 3
      vendor/github.com/moby/buildkit/solver/cachemanager.go
  32. 6 3
      vendor/github.com/moby/buildkit/solver/exporter.go
  33. 3 2
      vendor/github.com/moby/buildkit/source/git/gitsource.go
  34. 193 28
      vendor/github.com/moby/buildkit/util/resolver/resolver.go
  35. 6 0
      vendor/github.com/moby/buildkit/util/tracing/tracing.go
  36. 5 1
      vendor/github.com/tonistiigi/fsutil/tarwriter.go

+ 5 - 36
builder/builder-next/adapters/containerimage/pull.go

@@ -31,13 +31,11 @@ import (
 	"github.com/moby/buildkit/cache"
 	"github.com/moby/buildkit/client/llb"
 	"github.com/moby/buildkit/session"
-	"github.com/moby/buildkit/session/auth"
 	"github.com/moby/buildkit/source"
 	"github.com/moby/buildkit/util/flightcontrol"
 	"github.com/moby/buildkit/util/imageutil"
 	"github.com/moby/buildkit/util/progress"
 	"github.com/moby/buildkit/util/resolver"
-	"github.com/moby/buildkit/util/tracing"
 	digest "github.com/opencontainers/go-digest"
 	"github.com/opencontainers/image-spec/identity"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@@ -54,7 +52,7 @@ type SourceOpt struct {
 	DownloadManager distribution.RootFSDownloadManager
 	MetadataStore   metadata.V2MetadataService
 	ImageStore      image.Store
-	ResolverOpt     resolver.ResolveOptionsFunc
+	RegistryHosts   docker.RegistryHosts
 	LayerStore      layer.Store
 }
 
@@ -78,44 +76,15 @@ func (is *imageSource) ID() string {
 	return source.DockerImageScheme
 }
 
-func (is *imageSource) getResolver(ctx context.Context, rfn resolver.ResolveOptionsFunc, ref string, sm *session.Manager) remotes.Resolver {
+func (is *imageSource) getResolver(ctx context.Context, hosts docker.RegistryHosts, ref string, sm *session.Manager) remotes.Resolver {
 	if res := is.resolverCache.Get(ctx, ref); res != nil {
 		return res
 	}
-
-	opt := docker.ResolverOptions{
-		Client: tracing.DefaultClient,
-	}
-	if rfn != nil {
-		opt = rfn(ref)
-	}
-	opt.Credentials = is.getCredentialsFromSession(ctx, sm)
-	r := docker.NewResolver(opt)
+	r := resolver.New(ctx, hosts, sm)
 	r = is.resolverCache.Add(ctx, ref, r)
 	return r
 }
 
-func (is *imageSource) getCredentialsFromSession(ctx context.Context, sm *session.Manager) func(string) (string, string, error) {
-	id := session.FromContext(ctx)
-	if id == "" {
-		// can be removed after containerd/containerd#2812
-		return func(string) (string, string, error) {
-			return "", "", nil
-		}
-	}
-	return func(host string) (string, string, error) {
-		timeoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
-		defer cancel()
-
-		caller, err := sm.Get(timeoutCtx, id)
-		if err != nil {
-			return "", "", err
-		}
-
-		return auth.CredentialsFunc(tracing.ContextWithSpanFromContext(context.TODO(), ctx), caller)(host)
-	}
-}
-
 func (is *imageSource) resolveLocal(refStr string) (*image.Image, error) {
 	ref, err := distreference.ParseNormalizedNamed(refStr)
 	if err != nil {
@@ -138,7 +107,7 @@ func (is *imageSource) resolveRemote(ctx context.Context, ref string, platform *
 		dt   []byte
 	}
 	res, err := is.g.Do(ctx, ref, func(ctx context.Context) (interface{}, error) {
-		dgst, dt, err := imageutil.Config(ctx, ref, is.getResolver(ctx, is.ResolverOpt, ref, sm), is.ContentStore, nil, platform)
+		dgst, dt, err := imageutil.Config(ctx, ref, is.getResolver(ctx, is.RegistryHosts, ref, sm), is.ContentStore, nil, platform)
 		if err != nil {
 			return nil, err
 		}
@@ -208,7 +177,7 @@ func (is *imageSource) Resolve(ctx context.Context, id source.Identifier, sm *se
 	p := &puller{
 		src:      imageIdentifier,
 		is:       is,
-		resolver: is.getResolver(ctx, is.ResolverOpt, imageIdentifier.Reference.String(), sm),
+		resolver: is.getResolver(ctx, is.RegistryHosts, imageIdentifier.Reference.String(), sm),
 		platform: platform,
 		sm:       sm,
 	}

+ 3 - 3
builder/builder-next/adapters/localinlinecache/inlinecache.go

@@ -7,6 +7,7 @@ import (
 
 	"github.com/containerd/containerd/content"
 	"github.com/containerd/containerd/images"
+	"github.com/containerd/containerd/remotes/docker"
 	distreference "github.com/docker/distribution/reference"
 	imagestore "github.com/docker/docker/image"
 	"github.com/docker/docker/reference"
@@ -15,7 +16,6 @@ import (
 	v1 "github.com/moby/buildkit/cache/remotecache/v1"
 	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/solver"
-	"github.com/moby/buildkit/util/resolver"
 	"github.com/moby/buildkit/worker"
 	digest "github.com/opencontainers/go-digest"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
@@ -23,9 +23,9 @@ import (
 )
 
 // ResolveCacheImporterFunc returns a resolver function for local inline cache
-func ResolveCacheImporterFunc(sm *session.Manager, resolverOpt resolver.ResolveOptionsFunc, cs content.Store, rs reference.Store, is imagestore.Store) remotecache.ResolveCacheImporterFunc {
+func ResolveCacheImporterFunc(sm *session.Manager, resolverFunc docker.RegistryHosts, cs content.Store, rs reference.Store, is imagestore.Store) remotecache.ResolveCacheImporterFunc {
 
-	upstream := registryremotecache.ResolveCacheImporterFunc(sm, cs, resolverOpt)
+	upstream := registryremotecache.ResolveCacheImporterFunc(sm, cs, resolverFunc)
 
 	return func(ctx context.Context, attrs map[string]string) (remotecache.Importer, specs.Descriptor, error) {
 		if dt, err := tryImportLocal(rs, is, attrs["ref"]); err == nil {

+ 2 - 2
builder/builder-next/builder.go

@@ -11,6 +11,7 @@ import (
 	"time"
 
 	"github.com/containerd/containerd/platforms"
+	"github.com/containerd/containerd/remotes/docker"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/backend"
 	"github.com/docker/docker/builder"
@@ -26,7 +27,6 @@ import (
 	"github.com/moby/buildkit/identity"
 	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/util/entitlements"
-	"github.com/moby/buildkit/util/resolver"
 	"github.com/moby/buildkit/util/tracing"
 	"github.com/pkg/errors"
 	"golang.org/x/sync/errgroup"
@@ -70,7 +70,7 @@ type Opt struct {
 	Dist                images.DistributionServices
 	NetworkController   libnetwork.NetworkController
 	DefaultCgroupParent string
-	ResolverOpt         resolver.ResolveOptionsFunc
+	RegistryHosts       docker.RegistryHosts
 	BuilderConfig       config.BuilderConfig
 	Rootless            bool
 	IdentityMapping     *idtools.IdentityMapping

+ 2 - 2
builder/builder-next/controller.go

@@ -119,7 +119,7 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
 		MetadataStore:   dist.V2MetadataService,
 		ImageStore:      dist.ImageStore,
 		ReferenceStore:  dist.ReferenceStore,
-		ResolverOpt:     opt.ResolverOpt,
+		RegistryHosts:   opt.RegistryHosts,
 		LayerStore:      dist.LayerStore,
 	})
 	if err != nil {
@@ -210,7 +210,7 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
 		Frontends:        frontends,
 		CacheKeyStorage:  cacheStorage,
 		ResolveCacheImporterFuncs: map[string]remotecache.ResolveCacheImporterFunc{
-			"registry": localinlinecache.ResolveCacheImporterFunc(opt.SessionManager, opt.ResolverOpt, store, dist.ReferenceStore, dist.ImageStore),
+			"registry": localinlinecache.ResolveCacheImporterFunc(opt.SessionManager, opt.RegistryHosts, store, dist.ReferenceStore, dist.ImageStore),
 			"local":    localremotecache.ResolveCacheImporterFunc(opt.SessionManager),
 		},
 		ResolveCacheExporterFuncs: map[string]remotecache.ResolveCacheExporterFunc{

+ 1 - 1
cmd/dockerd/daemon.go

@@ -292,7 +292,7 @@ func newRouterOptions(config *config.Config, d *daemon.Daemon) (routerOptions, e
 		Dist:                d.DistributionServices(),
 		NetworkController:   d.NetworkController(),
 		DefaultCgroupParent: cgroupParent,
-		ResolverOpt:         d.NewResolveOptionsFunc(),
+		RegistryHosts:       d.RegistryHosts(),
 		BuilderConfig:       config.Builder,
 		Rootless:            d.Rootless(),
 		IdentityMapping:     d.IdentityMapping(),

+ 35 - 54
daemon/daemon.go

@@ -9,7 +9,6 @@ import (
 	"context"
 	"fmt"
 	"io/ioutil"
-	"math/rand"
 	"net"
 	"net/url"
 	"os"
@@ -28,7 +27,6 @@ import (
 	"github.com/containerd/containerd/defaults"
 	"github.com/containerd/containerd/pkg/dialer"
 	"github.com/containerd/containerd/remotes/docker"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
 	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/api/types/swarm"
@@ -42,8 +40,8 @@ import (
 	"github.com/docker/docker/daemon/logger"
 	"github.com/docker/docker/daemon/network"
 	"github.com/docker/docker/errdefs"
+	bkconfig "github.com/moby/buildkit/cmd/buildkitd/config"
 	"github.com/moby/buildkit/util/resolver"
-	"github.com/moby/buildkit/util/tracing"
 	"github.com/sirupsen/logrus"
 
 	// register graph drivers
@@ -153,63 +151,46 @@ func (daemon *Daemon) Features() *map[string]bool {
 	return &daemon.configStore.Features
 }
 
-// NewResolveOptionsFunc returns a call back function to resolve "registry-mirrors" and
-// "insecure-registries" for buildkit
-func (daemon *Daemon) NewResolveOptionsFunc() resolver.ResolveOptionsFunc {
-	return func(ref string) docker.ResolverOptions {
-		var (
-			registryKey = "docker.io"
-			mirrors     = make([]string, len(daemon.configStore.Mirrors))
-			m           = map[string]resolver.RegistryConf{}
-		)
-		// must trim "https://" or "http://" prefix
-		for i, v := range daemon.configStore.Mirrors {
-			if uri, err := url.Parse(v); err == nil {
-				v = uri.Host
-			}
-			mirrors[i] = v
-		}
-		// set "registry-mirrors"
-		m[registryKey] = resolver.RegistryConf{Mirrors: mirrors}
-		// set "insecure-registries"
-		for _, v := range daemon.configStore.InsecureRegistries {
-			if uri, err := url.Parse(v); err == nil {
-				v = uri.Host
-			}
-			plainHTTP := true
-			m[v] = resolver.RegistryConf{
-				PlainHTTP: &plainHTTP,
-			}
-		}
-		def := docker.ResolverOptions{
-			Client: tracing.DefaultClient,
-		}
-
-		parsed, err := reference.ParseNormalizedNamed(ref)
-		if err != nil {
-			return def
+// RegistryHosts returns registry configuration in containerd resolvers format
+func (daemon *Daemon) RegistryHosts() docker.RegistryHosts {
+	var (
+		registryKey = "docker.io"
+		mirrors     = make([]string, len(daemon.configStore.Mirrors))
+		m           = map[string]bkconfig.RegistryConfig{}
+	)
+	// must trim "https://" or "http://" prefix
+	for i, v := range daemon.configStore.Mirrors {
+		if uri, err := url.Parse(v); err == nil {
+			v = uri.Host
 		}
-		host := reference.Domain(parsed)
-
-		c, ok := m[host]
-		if !ok {
-			return def
-		}
-
-		if len(c.Mirrors) > 0 {
-			// TODO ResolverOptions.Host is deprecated; ResolverOptions.Hosts should be used
-			def.Host = func(string) (string, error) {
-				return c.Mirrors[rand.Intn(len(c.Mirrors))], nil
+		mirrors[i] = v
+	}
+	// set mirrors for default registry
+	m[registryKey] = bkconfig.RegistryConfig{Mirrors: mirrors}
+
+	for _, v := range daemon.configStore.InsecureRegistries {
+		u, err := url.Parse(v)
+		c := bkconfig.RegistryConfig{}
+		if err == nil {
+			v = u.Host
+			t := true
+			if u.Scheme == "http" {
+				c.PlainHTTP = &t
+			} else {
+				c.Insecure = &t
 			}
 		}
+		m[v] = c
+	}
 
-		// TODO ResolverOptions.PlainHTTP is deprecated; ResolverOptions.Hosts should be used
-		if c.PlainHTTP != nil {
-			def.PlainHTTP = *c.PlainHTTP
+	for k, v := range m {
+		if d, err := registry.HostCertsDir(k); err == nil {
+			v.TLSConfigDir = []string{d}
+			m[k] = v
 		}
-
-		return def
 	}
+
+	return resolver.NewRegistryConfig(m)
 }
 
 func (daemon *Daemon) restore() error {

+ 21 - 11
registry/registry.go

@@ -26,6 +26,24 @@ var (
 	ErrAlreadyExists = errors.New("Image already exists")
 )
 
+// HostCertsDir returns the config directory for a specific host
+func HostCertsDir(hostname string) (string, error) {
+	certsDir := CertsDir
+
+	if rootless.RunningWithRootlessKit() {
+		configHome, err := homedir.GetConfigHome()
+		if err != nil {
+			return "", err
+		}
+
+		certsDir = filepath.Join(configHome, "docker/certs.d")
+	}
+
+	hostDir := filepath.Join(certsDir, cleanPath(hostname))
+
+	return hostDir, nil
+}
+
 func newTLSConfig(hostname string, isSecure bool) (*tls.Config, error) {
 	// PreferredServerCipherSuites should have no effect
 	tlsConfig := tlsconfig.ServerDefault()
@@ -33,19 +51,11 @@ func newTLSConfig(hostname string, isSecure bool) (*tls.Config, error) {
 	tlsConfig.InsecureSkipVerify = !isSecure
 
 	if isSecure && CertsDir != "" {
-		certsDir := CertsDir
-
-		if rootless.RunningWithRootlessKit() {
-			configHome, err := homedir.GetConfigHome()
-			if err != nil {
-				return nil, err
-			}
-
-			certsDir = filepath.Join(configHome, "docker/certs.d")
+		hostDir, err := HostCertsDir(hostname)
+		if err != nil {
+			return nil, err
 		}
 
-		hostDir := filepath.Join(certsDir, cleanPath(hostname))
-
 		logrus.Debugf("hostDir: %s", hostDir)
 		if err := ReadCertsDirectory(tlsConfig, hostDir); err != nil {
 			return nil, err

+ 2 - 2
vendor.conf

@@ -27,8 +27,8 @@ github.com/imdario/mergo                            1afb36080aec31e0d1528973ebe6
 golang.org/x/sync                                   cd5d95a43a6e21273425c7ae415d3df9ea832eeb
 
 # buildkit
-github.com/moby/buildkit                            4d8d91bf49c769b8458e9aa84746c842b4a0e39a
-github.com/tonistiigi/fsutil                        013a9fe6aee2d1658457075bf9e688bc8c0be2e0
+github.com/moby/buildkit                            ae7ff7174f73bcb4df89b97e1623b3fb0bfb0a0c
+github.com/tonistiigi/fsutil                        c2c7d7b0e1441705cd802e5699c0a10b1dfe39fd
 github.com/grpc-ecosystem/grpc-opentracing          8e809c8a86450a29b90dcc9efbf062d0fe6d9746
 github.com/opentracing/opentracing-go               1361b9cd60be79c4c3a7fa9841b3c132e40066a7
 github.com/google/shlex                             e7afc7fbc51079733e9468cdfd1efcd7d196cd1d

+ 5 - 4
vendor/github.com/moby/buildkit/README.md

@@ -128,7 +128,7 @@ 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 `rm -f $(which buildkit-runc) && ln -s $(which crun) /usr/local/bin/buildkit-runc` .
+* 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
@@ -205,8 +205,8 @@ By default, the build result and intermediate cache will only remain internally
 buildctl build ... --output type=image,name=docker.io/username/image,push=true
 ```
 
-To export and import the cache along with the image, you need to specify `--export-cache type=inline` and `--import-cache type=registry,ref=...`.
-See [Export cache](#export-cache).
+To export the cache embed with the image and pushing them to registry together, type `registry` is required to import the cache, you should specify `--export-cache type=inline` and `--import-cache type=registry,ref=...`. To export the cache to a local directy, you should specify `--export-cache type=local`.
+Details in [Export cache](#export-cache).
 
 ```bash
 buildctl build ...\
@@ -357,7 +357,8 @@ The directory layout conforms to OCI Image Spec v1.0.
 -   `ref=docker.io/user/image:tag`: reference for `registry` cache importer
 -   `src=path/to/input-dir`: directory for `local` cache importer
 -   `digest=sha256:deadbeef`: digest of the manifest list to import for `local` cache importer.
-    Defaults to the digest of "latest" tag in `index.json`
+-   `tag=customtag`: custom tag of image for `local` cache importer.
+    Defaults to the digest of "latest" tag in `index.json` is for digest, not for tag
 
 ### Consistent hashing
 

+ 4 - 1
vendor/github.com/moby/buildkit/cache/contenthash/tarsum.go

@@ -5,6 +5,7 @@ import (
 	"io"
 	"sort"
 	"strconv"
+	"strings"
 )
 
 // WriteV1TarsumHeaders writes a tar header to a writer in V1 tarsum format.
@@ -38,7 +39,9 @@ func v1TarHeaderSelect(h *tar.Header) (orderedHeaders [][2]string) {
 	// Get extended attributes.
 	xAttrKeys := make([]string, len(h.Xattrs))
 	for k := range h.Xattrs {
-		xAttrKeys = append(xAttrKeys, k)
+		if !strings.HasPrefix(k, "security.") && !strings.HasPrefix(k, "system.") {
+			xAttrKeys = append(xAttrKeys, k)
+		}
 	}
 	sort.Strings(xAttrKeys)
 

+ 4 - 31
vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go

@@ -2,15 +2,12 @@ package registry
 
 import (
 	"context"
-	"time"
 
 	"github.com/containerd/containerd/content"
-	"github.com/containerd/containerd/remotes"
 	"github.com/containerd/containerd/remotes/docker"
 	"github.com/docker/distribution/reference"
 	"github.com/moby/buildkit/cache/remotecache"
 	"github.com/moby/buildkit/session"
-	"github.com/moby/buildkit/session/auth"
 	"github.com/moby/buildkit/util/contentutil"
 	"github.com/moby/buildkit/util/resolver"
 	"github.com/opencontainers/go-digest"
@@ -34,13 +31,13 @@ const (
 	attrRef = "ref"
 )
 
-func ResolveCacheExporterFunc(sm *session.Manager, resolverOpt resolver.ResolveOptionsFunc) remotecache.ResolveCacheExporterFunc {
+func ResolveCacheExporterFunc(sm *session.Manager, hosts docker.RegistryHosts) remotecache.ResolveCacheExporterFunc {
 	return func(ctx context.Context, attrs map[string]string) (remotecache.Exporter, error) {
 		ref, err := canonicalizeRef(attrs[attrRef])
 		if err != nil {
 			return nil, err
 		}
-		remote := newRemoteResolver(ctx, resolverOpt, sm, ref)
+		remote := resolver.New(ctx, hosts, sm)
 		pusher, err := remote.Pusher(ctx, ref)
 		if err != nil {
 			return nil, err
@@ -49,13 +46,13 @@ func ResolveCacheExporterFunc(sm *session.Manager, resolverOpt resolver.ResolveO
 	}
 }
 
-func ResolveCacheImporterFunc(sm *session.Manager, cs content.Store, resolverOpt resolver.ResolveOptionsFunc) remotecache.ResolveCacheImporterFunc {
+func ResolveCacheImporterFunc(sm *session.Manager, cs content.Store, hosts docker.RegistryHosts) remotecache.ResolveCacheImporterFunc {
 	return func(ctx context.Context, attrs map[string]string) (remotecache.Importer, specs.Descriptor, error) {
 		ref, err := canonicalizeRef(attrs[attrRef])
 		if err != nil {
 			return nil, specs.Descriptor{}, err
 		}
-		remote := newRemoteResolver(ctx, resolverOpt, sm, ref)
+		remote := resolver.New(ctx, hosts, sm)
 		xref, desc, err := remote.Resolve(ctx, ref)
 		if err != nil {
 			return nil, specs.Descriptor{}, err
@@ -97,27 +94,3 @@ func (dsl *withDistributionSourceLabel) SetDistributionSourceAnnotation(desc oci
 	desc.Annotations["containerd.io/distribution.source.ref"] = dsl.ref
 	return desc
 }
-
-func newRemoteResolver(ctx context.Context, resolverOpt resolver.ResolveOptionsFunc, sm *session.Manager, ref string) remotes.Resolver {
-	opt := resolverOpt(ref)
-	opt.Credentials = getCredentialsFunc(ctx, sm)
-	return docker.NewResolver(opt)
-}
-
-func getCredentialsFunc(ctx context.Context, sm *session.Manager) func(string) (string, string, error) {
-	id := session.FromContext(ctx)
-	if id == "" {
-		return nil
-	}
-	return func(host string) (string, string, error) {
-		timeoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
-		defer cancel()
-
-		caller, err := sm.Get(timeoutCtx, id)
-		if err != nil {
-			return "", "", err
-		}
-
-		return auth.CredentialsFunc(context.TODO(), caller)(host)
-	}
-}

+ 6 - 0
vendor/github.com/moby/buildkit/client/client.go

@@ -11,6 +11,8 @@ import (
 	"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
 	controlapi "github.com/moby/buildkit/api/services/control"
 	"github.com/moby/buildkit/client/connhelper"
+	"github.com/moby/buildkit/session"
+	"github.com/moby/buildkit/session/grpchijack"
 	"github.com/moby/buildkit/util/appdefaults"
 	opentracing "github.com/opentracing/opentracing-go"
 	"github.com/pkg/errors"
@@ -80,6 +82,10 @@ func (c *Client) controlClient() controlapi.ControlClient {
 	return controlapi.NewControlClient(c.conn)
 }
 
+func (c *Client) Dialer() session.Dialer {
+	return grpchijack.Dialer(c.controlClient())
+}
+
 func (c *Client) Close() error {
 	return c.conn.Close()
 }

+ 98 - 0
vendor/github.com/moby/buildkit/client/llb/async.go

@@ -0,0 +1,98 @@
+package llb
+
+import (
+	"context"
+
+	"github.com/moby/buildkit/solver/pb"
+	"github.com/moby/buildkit/util/flightcontrol"
+	digest "github.com/opencontainers/go-digest"
+	"github.com/pkg/errors"
+)
+
+type asyncState struct {
+	f      func(context.Context, State) (State, error)
+	prev   State
+	target State
+	set    bool
+	err    error
+	g      flightcontrol.Group
+}
+
+func (as *asyncState) Output() Output {
+	return as
+}
+
+func (as *asyncState) Vertex(ctx context.Context) Vertex {
+	err := as.Do(ctx)
+	if err != nil {
+		return &errVertex{err}
+	}
+	if as.set {
+		out := as.target.Output()
+		if out == nil {
+			return nil
+		}
+		return out.Vertex(ctx)
+	}
+	return nil
+}
+
+func (as *asyncState) ToInput(ctx context.Context, c *Constraints) (*pb.Input, error) {
+	err := as.Do(ctx)
+	if err != nil {
+		return nil, err
+	}
+	if as.set {
+		out := as.target.Output()
+		if out == nil {
+			return nil, nil
+		}
+		return out.ToInput(ctx, c)
+	}
+	return nil, nil
+}
+
+func (as *asyncState) Do(ctx context.Context) error {
+	_, err := as.g.Do(ctx, "", func(ctx context.Context) (interface{}, error) {
+		if as.set {
+			return as.target, as.err
+		}
+		res, err := as.f(ctx, as.prev)
+		if err != nil {
+			select {
+			case <-ctx.Done():
+				if errors.Cause(err) == ctx.Err() {
+					return res, err
+				}
+			default:
+			}
+		}
+		as.target = res
+		as.err = err
+		as.set = true
+		return res, err
+	})
+	if err != nil {
+		return err
+	}
+	return as.err
+}
+
+type errVertex struct {
+	err error
+}
+
+func (v *errVertex) Validate(context.Context) error {
+	return v.err
+}
+func (v *errVertex) Marshal(context.Context, *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
+	return "", nil, nil, v.err
+}
+func (v *errVertex) Output() Output {
+	return nil
+}
+func (v *errVertex) Inputs() []Output {
+	return nil
+}
+
+var _ Vertex = &errVertex{}

+ 35 - 25
vendor/github.com/moby/buildkit/client/llb/definition.go

@@ -1,6 +1,9 @@
 package llb
 
 import (
+	"context"
+	"sync"
+
 	"github.com/moby/buildkit/solver/pb"
 	digest "github.com/opencontainers/go-digest"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
@@ -13,6 +16,7 @@ import (
 // LLB state can be reconstructed from the definition.
 type DefinitionOp struct {
 	MarshalCache
+	mu        sync.Mutex
 	ops       map[digest.Digest]*pb.Op
 	defs      map[digest.Digest][]byte
 	metas     map[digest.Digest]pb.OpMetadata
@@ -25,6 +29,7 @@ type DefinitionOp struct {
 func NewDefinitionOp(def *pb.Definition) (*DefinitionOp, error) {
 	ops := make(map[digest.Digest]*pb.Op)
 	defs := make(map[digest.Digest][]byte)
+	platforms := make(map[digest.Digest]*specs.Platform)
 
 	var dgst digest.Digest
 	for _, dt := range def.Def {
@@ -35,6 +40,13 @@ func NewDefinitionOp(def *pb.Definition) (*DefinitionOp, error) {
 		dgst = digest.FromBytes(dt)
 		ops[dgst] = &op
 		defs[dgst] = dt
+
+		var platform *specs.Platform
+		if op.Platform != nil {
+			spec := op.Platform.Spec()
+			platform = &spec
+		}
+		platforms[dgst] = platform
 	}
 
 	var index pb.OutputIndex
@@ -47,26 +59,29 @@ func NewDefinitionOp(def *pb.Definition) (*DefinitionOp, error) {
 		ops:       ops,
 		defs:      defs,
 		metas:     def.Metadata,
-		platforms: make(map[digest.Digest]*specs.Platform),
+		platforms: platforms,
 		dgst:      dgst,
 		index:     index,
 	}, nil
 }
 
-func (d *DefinitionOp) ToInput(c *Constraints) (*pb.Input, error) {
-	return d.Output().ToInput(c)
+func (d *DefinitionOp) ToInput(ctx context.Context, c *Constraints) (*pb.Input, error) {
+	return d.Output().ToInput(ctx, c)
 }
 
-func (d *DefinitionOp) Vertex() Vertex {
+func (d *DefinitionOp) Vertex(context.Context) Vertex {
 	return d
 }
 
-func (d *DefinitionOp) Validate() error {
+func (d *DefinitionOp) Validate(context.Context) error {
 	// Scratch state has no digest, ops or metas.
 	if d.dgst == "" {
 		return nil
 	}
 
+	d.mu.Lock()
+	defer d.mu.Unlock()
+
 	if len(d.ops) == 0 || len(d.defs) == 0 || len(d.metas) == 0 {
 		return errors.Errorf("invalid definition op with no ops %d %d", len(d.ops), len(d.metas))
 	}
@@ -95,15 +110,18 @@ func (d *DefinitionOp) Validate() error {
 	return nil
 }
 
-func (d *DefinitionOp) Marshal(c *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
+func (d *DefinitionOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
 	if d.dgst == "" {
 		return "", nil, nil, errors.Errorf("cannot marshal empty definition op")
 	}
 
-	if err := d.Validate(); err != nil {
+	if err := d.Validate(ctx); err != nil {
 		return "", nil, nil, err
 	}
 
+	d.mu.Lock()
+	defer d.mu.Unlock()
+
 	meta := d.metas[d.dgst]
 	return d.dgst, d.defs[d.dgst], &meta, nil
 
@@ -114,7 +132,11 @@ func (d *DefinitionOp) Output() Output {
 		return nil
 	}
 
-	return &output{vertex: d, platform: d.platform(), getIndex: func() (pb.OutputIndex, error) {
+	d.mu.Lock()
+	platform := d.platforms[d.dgst]
+	d.mu.Unlock()
+
+	return &output{vertex: d, platform: platform, getIndex: func() (pb.OutputIndex, error) {
 		return d.index, nil
 	}}
 }
@@ -126,7 +148,11 @@ func (d *DefinitionOp) Inputs() []Output {
 
 	var inputs []Output
 
+	d.mu.Lock()
 	op := d.ops[d.dgst]
+	platform := d.platforms[d.dgst]
+	d.mu.Unlock()
+
 	for _, input := range op.Inputs {
 		vtx := &DefinitionOp{
 			ops:       d.ops,
@@ -136,26 +162,10 @@ func (d *DefinitionOp) Inputs() []Output {
 			dgst:      input.Digest,
 			index:     input.Index,
 		}
-		inputs = append(inputs, &output{vertex: vtx, platform: d.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 inputs
 }
-
-func (d *DefinitionOp) platform() *specs.Platform {
-	platform, ok := d.platforms[d.dgst]
-	if ok {
-		return platform
-	}
-
-	op := d.ops[d.dgst]
-	if op.Platform != nil {
-		spec := op.Platform.Spec()
-		platform = &spec
-	}
-
-	d.platforms[d.dgst] = platform
-	return platform
-}

+ 82 - 81
vendor/github.com/moby/buildkit/client/llb/exec.go

@@ -1,6 +1,7 @@
 package llb
 
 import (
+	"context"
 	_ "crypto/sha256"
 	"fmt"
 	"net"
@@ -12,19 +13,9 @@ import (
 	"github.com/pkg/errors"
 )
 
-type Meta struct {
-	Args       []string
-	Env        EnvList
-	Cwd        string
-	User       string
-	ProxyEnv   *ProxyEnv
-	ExtraHosts []HostIP
-	Network    pb.NetMode
-	Security   pb.SecurityMode
-}
-
-func NewExecOp(root Output, meta Meta, readOnly bool, c Constraints) *ExecOp {
-	e := &ExecOp{meta: meta, constraints: c}
+func NewExecOp(base State, proxyEnv *ProxyEnv, readOnly bool, c Constraints) *ExecOp {
+	e := &ExecOp{base: base, constraints: c, proxyEnv: proxyEnv}
+	root := base.Output()
 	rootMount := &mount{
 		target:   pb.RootMount,
 		source:   root,
@@ -58,9 +49,10 @@ type mount struct {
 
 type ExecOp struct {
 	MarshalCache
+	proxyEnv    *ProxyEnv
 	root        Output
 	mounts      []*mount
-	meta        Meta
+	base        State
 	constraints Constraints
 	isValidated bool
 	secrets     []SecretInfo
@@ -103,19 +95,27 @@ func (e *ExecOp) GetMount(target string) Output {
 	return nil
 }
 
-func (e *ExecOp) Validate() error {
+func (e *ExecOp) Validate(ctx context.Context) error {
 	if e.isValidated {
 		return nil
 	}
-	if len(e.meta.Args) == 0 {
+	args, err := getArgs(e.base)(ctx)
+	if err != nil {
+		return err
+	}
+	if len(args) == 0 {
 		return errors.Errorf("arguments are required")
 	}
-	if e.meta.Cwd == "" {
+	cwd, err := getDir(e.base)(ctx)
+	if err != nil {
+		return err
+	}
+	if cwd == "" {
 		return errors.Errorf("working directory is required")
 	}
 	for _, m := range e.mounts {
 		if m.source != nil {
-			if err := m.source.Vertex().Validate(); err != nil {
+			if err := m.source.Vertex(ctx).Validate(ctx); err != nil {
 				return err
 			}
 		}
@@ -124,11 +124,11 @@ func (e *ExecOp) Validate() error {
 	return nil
 }
 
-func (e *ExecOp) Marshal(c *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
+func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
 	if e.Cached(c) {
 		return e.Load()
 	}
-	if err := e.Validate(); err != nil {
+	if err := e.Validate(ctx); err != nil {
 		return "", nil, nil, err
 	}
 	// make sure mounts are sorted
@@ -136,52 +136,86 @@ func (e *ExecOp) Marshal(c *Constraints) (digest.Digest, []byte, *pb.OpMetadata,
 		return e.mounts[i].target < e.mounts[j].target
 	})
 
+	env, err := getEnv(e.base)(ctx)
+	if err != nil {
+		return "", nil, nil, err
+	}
+
 	if len(e.ssh) > 0 {
 		for i, s := range e.ssh {
 			if s.Target == "" {
 				e.ssh[i].Target = fmt.Sprintf("/run/buildkit/ssh_agent.%d", i)
 			}
 		}
-		if _, ok := e.meta.Env.Get("SSH_AUTH_SOCK"); !ok {
-			e.meta.Env = e.meta.Env.AddOrReplace("SSH_AUTH_SOCK", e.ssh[0].Target)
+		if _, ok := env.Get("SSH_AUTH_SOCK"); !ok {
+			env = env.AddOrReplace("SSH_AUTH_SOCK", e.ssh[0].Target)
 		}
 	}
 	if c.Caps != nil {
 		if err := c.Caps.Supports(pb.CapExecMetaSetsDefaultPath); err != nil {
-			e.meta.Env = e.meta.Env.SetDefault("PATH", system.DefaultPathEnv)
+			env = env.SetDefault("PATH", system.DefaultPathEnv)
 		} else {
 			addCap(&e.constraints, pb.CapExecMetaSetsDefaultPath)
 		}
 	}
 
+	args, err := getArgs(e.base)(ctx)
+	if err != nil {
+		return "", nil, nil, err
+	}
+
+	cwd, err := getDir(e.base)(ctx)
+	if err != nil {
+		return "", nil, nil, err
+	}
+
+	user, err := getUser(e.base)(ctx)
+	if err != nil {
+		return "", nil, nil, err
+	}
+
 	meta := &pb.Meta{
-		Args: e.meta.Args,
-		Env:  e.meta.Env.ToArray(),
-		Cwd:  e.meta.Cwd,
-		User: e.meta.User,
-	}
-	if len(e.meta.ExtraHosts) > 0 {
-		hosts := make([]*pb.HostIP, len(e.meta.ExtraHosts))
-		for i, h := range e.meta.ExtraHosts {
+		Args: args,
+		Env:  env.ToArray(),
+		Cwd:  cwd,
+		User: user,
+	}
+	extraHosts, err := getExtraHosts(e.base)(ctx)
+	if err != nil {
+		return "", nil, nil, err
+	}
+	if len(extraHosts) > 0 {
+		hosts := make([]*pb.HostIP, len(extraHosts))
+		for i, h := range extraHosts {
 			hosts[i] = &pb.HostIP{Host: h.Host, IP: h.IP.String()}
 		}
 		meta.ExtraHosts = hosts
 	}
 
+	network, err := getNetwork(e.base)(ctx)
+	if err != nil {
+		return "", nil, nil, err
+	}
+
+	security, err := getSecurity(e.base)(ctx)
+	if err != nil {
+		return "", nil, nil, err
+	}
+
 	peo := &pb.ExecOp{
 		Meta:     meta,
-		Network:  e.meta.Network,
-		Security: e.meta.Security,
+		Network:  network,
+		Security: security,
 	}
-	if e.meta.Network != NetModeSandbox {
+	if network != NetModeSandbox {
 		addCap(&e.constraints, pb.CapExecMetaNetwork)
 	}
 
-	if e.meta.Security != SecurityModeSandbox {
+	if security != SecurityModeSandbox {
 		addCap(&e.constraints, pb.CapExecMetaSecurity)
 	}
 
-	if p := e.meta.ProxyEnv; p != nil {
+	if p := e.proxyEnv; p != nil {
 		peo.Meta.ProxyEnv = &pb.ProxyEnv{
 			HttpProxy:  p.HttpProxy,
 			HttpsProxy: p.HttpsProxy,
@@ -215,6 +249,14 @@ func (e *ExecOp) Marshal(c *Constraints) (digest.Digest, []byte, *pb.OpMetadata,
 		addCap(&e.constraints, pb.CapExecMountSSH)
 	}
 
+	if e.constraints.Platform == nil {
+		p, err := getPlatform(e.base)(ctx)
+		if err != nil {
+			return "", nil, nil, err
+		}
+		e.constraints.Platform = p
+	}
+
 	pop, md := MarshalConstraints(c, &e.constraints)
 	pop.Op = &pb.Op_Exec{
 		Exec: peo,
@@ -227,7 +269,7 @@ func (e *ExecOp) Marshal(c *Constraints) (digest.Digest, []byte, *pb.OpMetadata,
 			if m.tmpfs {
 				return "", nil, nil, errors.Errorf("tmpfs mounts must use scratch")
 			}
-			inp, err := m.source.ToInput(c)
+			inp, err := m.source.ToInput(ctx, c)
 			if err != nil {
 				return "", nil, nil, err
 			}
@@ -414,17 +456,11 @@ func (fn runOptionFunc) SetRunOption(ei *ExecInfo) {
 	fn(ei)
 }
 
-func Network(n pb.NetMode) RunOption {
-	return runOptionFunc(func(ei *ExecInfo) {
-		ei.State = network(n)(ei.State)
-	})
+func (fn StateOption) SetRunOption(ei *ExecInfo) {
+	ei.State = ei.State.With(fn)
 }
 
-func Security(s pb.SecurityMode) RunOption {
-	return runOptionFunc(func(ei *ExecInfo) {
-		ei.State = security(s)(ei.State)
-	})
-}
+var _ RunOption = StateOption(func(_ State) State { return State{} })
 
 func Shlex(str string) RunOption {
 	return runOptionFunc(func(ei *ExecInfo) {
@@ -443,47 +479,12 @@ func Args(a []string) RunOption {
 	})
 }
 
-func AddEnv(key, value string) RunOption {
-	return runOptionFunc(func(ei *ExecInfo) {
-		ei.State = ei.State.AddEnv(key, value)
-	})
-}
-
-func AddEnvf(key, value string, v ...interface{}) RunOption {
-	return runOptionFunc(func(ei *ExecInfo) {
-		ei.State = ei.State.AddEnvf(key, value, v...)
-	})
-}
-
-func User(str string) RunOption {
-	return runOptionFunc(func(ei *ExecInfo) {
-		ei.State = ei.State.User(str)
-	})
-}
-
-func Dir(str string) RunOption {
-	return runOptionFunc(func(ei *ExecInfo) {
-		ei.State = ei.State.Dir(str)
-	})
-}
-func Dirf(str string, v ...interface{}) RunOption {
-	return runOptionFunc(func(ei *ExecInfo) {
-		ei.State = ei.State.Dirf(str, v...)
-	})
-}
-
 func AddExtraHost(host string, ip net.IP) RunOption {
 	return runOptionFunc(func(ei *ExecInfo) {
 		ei.State = ei.State.AddExtraHost(host, ip)
 	})
 }
 
-func Reset(s State) RunOption {
-	return runOptionFunc(func(ei *ExecInfo) {
-		ei.State = ei.State.Reset(s)
-	})
-}
-
 func With(so ...StateOption) RunOption {
 	return runOptionFunc(func(ei *ExecInfo) {
 		ei.State = ei.State.With(so...)

+ 45 - 22
vendor/github.com/moby/buildkit/client/llb/fileop.go

@@ -1,6 +1,7 @@
 package llb
 
 import (
+	"context"
 	_ "crypto/sha256"
 	"os"
 	"path"
@@ -52,7 +53,7 @@ type CopyInput interface {
 }
 
 type subAction interface {
-	toProtoAction(string, pb.InputIndex) pb.IsFileAction
+	toProtoAction(context.Context, string, pb.InputIndex) (pb.IsFileAction, error)
 }
 
 type FileAction struct {
@@ -146,7 +147,7 @@ type fileActionMkdir struct {
 	info MkdirInfo
 }
 
-func (a *fileActionMkdir) toProtoAction(parent string, base pb.InputIndex) pb.IsFileAction {
+func (a *fileActionMkdir) toProtoAction(ctx context.Context, parent string, base pb.InputIndex) (pb.IsFileAction, error) {
 	return &pb.FileAction_Mkdir{
 		Mkdir: &pb.FileActionMkDir{
 			Path:        normalizePath(parent, a.file, false),
@@ -155,7 +156,7 @@ func (a *fileActionMkdir) toProtoAction(parent string, base pb.InputIndex) pb.Is
 			Owner:       a.info.ChownOpt.marshal(base),
 			Timestamp:   marshalTime(a.info.CreatedTime),
 		},
-	}
+	}, nil
 }
 
 type MkdirOption interface {
@@ -315,7 +316,7 @@ type fileActionMkfile struct {
 	info MkfileInfo
 }
 
-func (a *fileActionMkfile) toProtoAction(parent string, base pb.InputIndex) pb.IsFileAction {
+func (a *fileActionMkfile) toProtoAction(ctx context.Context, parent string, base pb.InputIndex) (pb.IsFileAction, error) {
 	return &pb.FileAction_Mkfile{
 		Mkfile: &pb.FileActionMkFile{
 			Path:      normalizePath(parent, a.file, false),
@@ -324,7 +325,7 @@ func (a *fileActionMkfile) toProtoAction(parent string, base pb.InputIndex) pb.I
 			Owner:     a.info.ChownOpt.marshal(base),
 			Timestamp: marshalTime(a.info.CreatedTime),
 		},
-	}
+	}, nil
 }
 
 func Rm(p string, opts ...RmOption) *FileAction {
@@ -379,14 +380,14 @@ type fileActionRm struct {
 	info RmInfo
 }
 
-func (a *fileActionRm) toProtoAction(parent string, base pb.InputIndex) pb.IsFileAction {
+func (a *fileActionRm) toProtoAction(ctx context.Context, parent string, base pb.InputIndex) (pb.IsFileAction, error) {
 	return &pb.FileAction_Rm{
 		Rm: &pb.FileActionRm{
 			Path:          normalizePath(parent, a.file, false),
 			AllowNotFound: a.info.AllowNotFound,
 			AllowWildcard: a.info.AllowWildcard,
 		},
-	}
+	}, nil
 }
 
 func Copy(input CopyInput, src, dest string, opts ...CopyOption) *FileAction {
@@ -448,9 +449,13 @@ type fileActionCopy struct {
 	info  CopyInfo
 }
 
-func (a *fileActionCopy) toProtoAction(parent string, base pb.InputIndex) pb.IsFileAction {
+func (a *fileActionCopy) toProtoAction(ctx context.Context, parent string, base pb.InputIndex) (pb.IsFileAction, error) {
+	src, err := a.sourcePath(ctx)
+	if err != nil {
+		return nil, err
+	}
 	c := &pb.FileActionCopy{
-		Src:                              a.sourcePath(),
+		Src:                              src,
 		Dest:                             normalizePath(parent, a.dest, true),
 		Owner:                            a.info.ChownOpt.marshal(base),
 		AllowWildcard:                    a.info.AllowWildcard,
@@ -468,19 +473,27 @@ func (a *fileActionCopy) toProtoAction(parent string, base pb.InputIndex) pb.IsF
 	}
 	return &pb.FileAction_Copy{
 		Copy: c,
-	}
+	}, nil
 }
 
-func (c *fileActionCopy) sourcePath() string {
+func (c *fileActionCopy) sourcePath(ctx context.Context) (string, error) {
 	p := path.Clean(c.src)
 	if !path.IsAbs(p) {
 		if c.state != nil {
-			p = path.Join("/", c.state.GetDir(), p)
+			dir, err := c.state.GetDir(ctx)
+			if err != nil {
+				return "", err
+			}
+			p = path.Join("/", dir, p)
 		} else if c.fas != nil {
-			p = path.Join("/", c.fas.state.GetDir(), p)
+			dir, err := c.fas.state.GetDir(ctx)
+			if err != nil {
+				return "", err
+			}
+			p = path.Join("/", dir, p)
 		}
 	}
-	return p
+	return p, nil
 }
 
 type CreatedTime time.Time
@@ -517,7 +530,7 @@ type FileOp struct {
 	isValidated bool
 }
 
-func (f *FileOp) Validate() error {
+func (f *FileOp) Validate(context.Context) error {
 	if f.isValidated {
 		return nil
 	}
@@ -529,14 +542,16 @@ func (f *FileOp) Validate() error {
 }
 
 type marshalState struct {
+	ctx     context.Context
 	visited map[*FileAction]*fileActionState
 	inputs  []*pb.Input
 	actions []*fileActionState
 }
 
-func newMarshalState() *marshalState {
+func newMarshalState(ctx context.Context) *marshalState {
 	return &marshalState{
 		visited: map[*FileAction]*fileActionState{},
+		ctx:     ctx,
 	}
 }
 
@@ -552,7 +567,7 @@ type fileActionState struct {
 }
 
 func (ms *marshalState) addInput(st *fileActionState, c *Constraints, o Output) (pb.InputIndex, error) {
-	inp, err := o.ToInput(c)
+	inp, err := o.ToInput(ms.ctx, c)
 	if err != nil {
 		return 0, err
 	}
@@ -634,11 +649,11 @@ func (ms *marshalState) add(fa *FileAction, c *Constraints) (*fileActionState, e
 	return st, nil
 }
 
-func (f *FileOp) Marshal(c *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
+func (f *FileOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
 	if f.Cached(c) {
 		return f.Load()
 	}
-	if err := f.Validate(); err != nil {
+	if err := f.Validate(ctx); err != nil {
 		return "", nil, nil, err
 	}
 
@@ -651,7 +666,7 @@ func (f *FileOp) Marshal(c *Constraints) (digest.Digest, []byte, *pb.OpMetadata,
 		File: pfo,
 	}
 
-	state := newMarshalState()
+	state := newMarshalState(ctx)
 	_, err := state.add(f.action, c)
 	if err != nil {
 		return "", nil, nil, err
@@ -666,14 +681,22 @@ func (f *FileOp) Marshal(c *Constraints) (digest.Digest, []byte, *pb.OpMetadata,
 
 		var parent string
 		if st.fa.state != nil {
-			parent = st.fa.state.GetDir()
+			parent, err = st.fa.state.GetDir(ctx)
+			if err != nil {
+				return "", nil, nil, err
+			}
+		}
+
+		action, err := st.action.toProtoAction(ctx, parent, st.base)
+		if err != nil {
+			return "", nil, nil, err
 		}
 
 		pfo.Actions = append(pfo.Actions, &pb.FileAction{
 			Input:          getIndex(st.input, len(state.inputs), st.inputRelative),
 			SecondaryInput: getIndex(st.input2, len(state.inputs), st.input2Relative),
 			Output:         output,
-			Action:         st.action.toProtoAction(parent, st.base),
+			Action:         action,
 		})
 	}
 

+ 128 - 58
vendor/github.com/moby/buildkit/client/llb/meta.go

@@ -1,6 +1,7 @@
 package llb
 
 import (
+	"context"
 	"fmt"
 	"net"
 	"path"
@@ -24,79 +25,122 @@ var (
 	keySecurity  = contextKeyT("llb.security")
 )
 
+func AddEnvf(key, value string, v ...interface{}) StateOption {
+	return addEnvf(key, value, true, v...)
+}
+
+func AddEnv(key, value string) StateOption {
+	return addEnvf(key, value, false)
+}
+
 func addEnvf(key, value string, replace bool, v ...interface{}) StateOption {
 	if replace {
 		value = fmt.Sprintf(value, v...)
 	}
 	return func(s State) State {
-		return s.WithValue(keyEnv, getEnv(s).AddOrReplace(key, value))
+		return s.withValue(keyEnv, func(ctx context.Context) (interface{}, error) {
+			env, err := getEnv(s)(ctx)
+			if err != nil {
+				return nil, err
+			}
+			return env.AddOrReplace(key, value), nil
+		})
 	}
 }
 
-func dir(str string) StateOption {
+func Dir(str string) StateOption {
 	return dirf(str, false)
 }
 
+func Dirf(str string, v ...interface{}) StateOption {
+	return dirf(str, true, v...)
+}
+
 func dirf(value string, replace bool, v ...interface{}) StateOption {
 	if replace {
 		value = fmt.Sprintf(value, v...)
 	}
 	return func(s State) State {
-		if !path.IsAbs(value) {
-			prev := getDir(s)
-			if prev == "" {
-				prev = "/"
+		return s.withValue(keyDir, func(ctx context.Context) (interface{}, error) {
+			if !path.IsAbs(value) {
+				prev, err := getDir(s)(ctx)
+				if err != nil {
+					return nil, err
+				}
+				if prev == "" {
+					prev = "/"
+				}
+				value = path.Join(prev, value)
 			}
-			value = path.Join(prev, value)
-		}
-		return s.WithValue(keyDir, value)
+			return value, nil
+		})
 	}
 }
 
-func user(str string) StateOption {
+func User(str string) StateOption {
 	return func(s State) State {
 		return s.WithValue(keyUser, str)
 	}
 }
 
-func reset(s_ State) StateOption {
+func Reset(other State) StateOption {
 	return func(s State) State {
 		s = NewState(s.Output())
-		s.ctx = s_.ctx
+		s.prev = &other
 		return s
 	}
 }
 
-func getEnv(s State) EnvList {
-	v := s.Value(keyEnv)
-	if v != nil {
-		return v.(EnvList)
+func getEnv(s State) func(context.Context) (EnvList, error) {
+	return func(ctx context.Context) (EnvList, error) {
+		v, err := s.getValue(keyEnv)(ctx)
+		if err != nil {
+			return nil, err
+		}
+		if v != nil {
+			return v.(EnvList), nil
+		}
+		return EnvList{}, nil
 	}
-	return EnvList{}
 }
 
-func getDir(s State) string {
-	v := s.Value(keyDir)
-	if v != nil {
-		return v.(string)
+func getDir(s State) func(context.Context) (string, error) {
+	return func(ctx context.Context) (string, error) {
+		v, err := s.getValue(keyDir)(ctx)
+		if err != nil {
+			return "", err
+		}
+		if v != nil {
+			return v.(string), nil
+		}
+		return "", nil
 	}
-	return ""
 }
 
-func getArgs(s State) []string {
-	v := s.Value(keyArgs)
-	if v != nil {
-		return v.([]string)
+func getArgs(s State) func(context.Context) ([]string, error) {
+	return func(ctx context.Context) ([]string, error) {
+		v, err := s.getValue(keyArgs)(ctx)
+		if err != nil {
+			return nil, err
+		}
+		if v != nil {
+			return v.([]string), nil
+		}
+		return nil, nil
 	}
-	return nil
 }
 
-func getUser(s State) string {
-	v := s.Value(keyUser)
-	if v != nil {
-		return v.(string)
+func getUser(s State) func(context.Context) (string, error) {
+	return func(ctx context.Context) (string, error) {
+		v, err := s.getValue(keyUser)(ctx)
+		if err != nil {
+			return "", err
+		}
+		if v != nil {
+			return v.(string), nil
+		}
+		return "", nil
 	}
-	return ""
 }
 
 func args(args ...string) StateOption {
@@ -124,27 +168,43 @@ func platform(p specs.Platform) StateOption {
 	}
 }
 
-func getPlatform(s State) *specs.Platform {
-	v := s.Value(keyPlatform)
-	if v != nil {
-		p := v.(specs.Platform)
-		return &p
+func getPlatform(s State) func(context.Context) (*specs.Platform, error) {
+	return func(ctx context.Context) (*specs.Platform, error) {
+		v, err := s.getValue(keyPlatform)(ctx)
+		if err != nil {
+			return nil, err
+		}
+		if v != nil {
+			p := v.(specs.Platform)
+			return &p, nil
+		}
+		return nil, nil
 	}
-	return nil
 }
 
 func extraHost(host string, ip net.IP) StateOption {
 	return func(s State) State {
-		return s.WithValue(keyExtraHost, append(getExtraHosts(s), HostIP{Host: host, IP: ip}))
+		return s.withValue(keyExtraHost, func(ctx context.Context) (interface{}, error) {
+			v, err := getExtraHosts(s)(ctx)
+			if err != nil {
+				return nil, err
+			}
+			return append(v, HostIP{Host: host, IP: ip}), nil
+		})
 	}
 }
 
-func getExtraHosts(s State) []HostIP {
-	v := s.Value(keyExtraHost)
-	if v != nil {
-		return v.([]HostIP)
+func getExtraHosts(s State) func(context.Context) ([]HostIP, error) {
+	return func(ctx context.Context) ([]HostIP, error) {
+		v, err := s.getValue(keyExtraHost)(ctx)
+		if err != nil {
+			return nil, err
+		}
+		if v != nil {
+			return v.([]HostIP), nil
+		}
+		return nil, nil
 	}
-	return nil
 }
 
 type HostIP struct {
@@ -152,32 +212,42 @@ type HostIP struct {
 	IP   net.IP
 }
 
-func network(v pb.NetMode) StateOption {
+func Network(v pb.NetMode) StateOption {
 	return func(s State) State {
 		return s.WithValue(keyNetwork, v)
 	}
 }
-func getNetwork(s State) pb.NetMode {
-	v := s.Value(keyNetwork)
-	if v != nil {
-		n := v.(pb.NetMode)
-		return n
+func getNetwork(s State) func(context.Context) (pb.NetMode, error) {
+	return func(ctx context.Context) (pb.NetMode, error) {
+		v, err := s.getValue(keyNetwork)(ctx)
+		if err != nil {
+			return 0, err
+		}
+		if v != nil {
+			n := v.(pb.NetMode)
+			return n, nil
+		}
+		return NetModeSandbox, nil
 	}
-	return NetModeSandbox
 }
 
-func security(v pb.SecurityMode) StateOption {
+func Security(v pb.SecurityMode) StateOption {
 	return func(s State) State {
 		return s.WithValue(keySecurity, v)
 	}
 }
-func getSecurity(s State) pb.SecurityMode {
-	v := s.Value(keySecurity)
-	if v != nil {
-		n := v.(pb.SecurityMode)
-		return n
+func getSecurity(s State) func(context.Context) (pb.SecurityMode, error) {
+	return func(ctx context.Context) (pb.SecurityMode, error) {
+		v, err := s.getValue(keySecurity)(ctx)
+		if err != nil {
+			return 0, err
+		}
+		if v != nil {
+			n := v.(pb.SecurityMode)
+			return n, nil
+		}
+		return SecurityModeSandbox, nil
 	}
-	return SecurityModeSandbox
 }
 
 type EnvList []KeyValue

+ 9 - 0
vendor/github.com/moby/buildkit/client/llb/resolver.go

@@ -14,6 +14,15 @@ func WithMetaResolver(mr ImageMetaResolver) ImageOption {
 	})
 }
 
+// ResolveDigest uses the meta resolver to update the ref of image with full digest before marshaling.
+// This makes image ref immutable and is recommended if you want to make sure meta resolver data
+// matches the image used during the build.
+func ResolveDigest(v bool) ImageOption {
+	return imageOptionFunc(func(ii *ImageInfo) {
+		ii.resolveDigest = v
+	})
+}
+
 // ImageMetaResolver can resolve image config metadata from a reference
 type ImageMetaResolver interface {
 	ResolveImageConfig(ctx context.Context, ref string, opt ResolveImageConfigOpt) (digest.Digest, []byte, error)

+ 37 - 21
vendor/github.com/moby/buildkit/client/llb/source.go

@@ -34,7 +34,7 @@ func NewSource(id string, attrs map[string]string, c Constraints) *SourceOp {
 	return s
 }
 
-func (s *SourceOp) Validate() error {
+func (s *SourceOp) Validate(ctx context.Context) error {
 	if s.err != nil {
 		return s.err
 	}
@@ -44,11 +44,11 @@ func (s *SourceOp) Validate() error {
 	return nil
 }
 
-func (s *SourceOp) Marshal(constraints *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
+func (s *SourceOp) Marshal(ctx context.Context, constraints *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
 	if s.Cached(constraints) {
 		return s.Load()
 	}
-	if err := s.Validate(); err != nil {
+	if err := s.Validate(ctx); err != nil {
 		return "", nil, nil, err
 	}
 
@@ -92,7 +92,8 @@ func (s *SourceOp) Inputs() []Output {
 func Image(ref string, opts ...ImageOption) State {
 	r, err := reference.ParseNormalizedNamed(ref)
 	if err == nil {
-		ref = reference.TagNameOnly(r).String()
+		r = reference.TagNameOnly(r)
+		ref = r.String()
 	}
 	var info ImageInfo
 	for _, opt := range opts {
@@ -116,21 +117,35 @@ func Image(ref string, opts ...ImageOption) State {
 	src := NewSource("docker-image://"+ref, attrs, info.Constraints) // controversial
 	if err != nil {
 		src.err = err
-	}
-	if info.metaResolver != nil {
-		_, dt, err := info.metaResolver.ResolveImageConfig(context.TODO(), ref, ResolveImageConfigOpt{
-			Platform:    info.Constraints.Platform,
-			ResolveMode: info.resolveMode.String(),
-		})
-		if err != nil {
-			src.err = err
-		} else {
-			st, err := NewState(src.Output()).WithImageConfig(dt)
-			if err == nil {
-				return st
-			}
-			src.err = err
+	} else if info.metaResolver != nil {
+		if _, ok := r.(reference.Digested); ok || !info.resolveDigest {
+			return NewState(src.Output()).Async(func(ctx context.Context, st State) (State, error) {
+				_, dt, err := info.metaResolver.ResolveImageConfig(ctx, ref, ResolveImageConfigOpt{
+					Platform:    info.Constraints.Platform,
+					ResolveMode: info.resolveMode.String(),
+				})
+				if err != nil {
+					return State{}, err
+				}
+				return st.WithImageConfig(dt)
+			})
 		}
+		return Scratch().Async(func(ctx context.Context, _ State) (State, error) {
+			dgst, dt, err := info.metaResolver.ResolveImageConfig(context.TODO(), ref, ResolveImageConfigOpt{
+				Platform:    info.Constraints.Platform,
+				ResolveMode: info.resolveMode.String(),
+			})
+			if err != nil {
+				return State{}, err
+			}
+			if dgst != "" {
+				r, err = reference.WithDigest(r, dgst)
+				if err != nil {
+					return State{}, err
+				}
+			}
+			return NewState(NewSource("docker-image://"+r.String(), attrs, info.Constraints).Output()).WithImageConfig(dt)
+		})
 	}
 	return NewState(src.Output())
 }
@@ -176,9 +191,10 @@ func (r ResolveMode) String() string {
 
 type ImageInfo struct {
 	constraintsWrapper
-	metaResolver ImageMetaResolver
-	resolveMode  ResolveMode
-	RecordType   string
+	metaResolver  ImageMetaResolver
+	resolveDigest bool
+	resolveMode   ResolveMode
+	RecordType    string
 }
 
 func Git(remote, ref string, opts ...GitOption) State {

+ 103 - 65
vendor/github.com/moby/buildkit/client/llb/state.go

@@ -18,13 +18,13 @@ import (
 type StateOption func(State) State
 
 type Output interface {
-	ToInput(*Constraints) (*pb.Input, error)
-	Vertex() Vertex
+	ToInput(context.Context, *Constraints) (*pb.Input, error)
+	Vertex(context.Context) Vertex
 }
 
 type Vertex interface {
-	Validate() error
-	Marshal(*Constraints) (digest.Digest, []byte, *pb.OpMetadata, error)
+	Validate(context.Context) error
+	Marshal(context.Context, *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error)
 	Output() Output
 	Inputs() []Output
 }
@@ -32,17 +32,18 @@ type Vertex interface {
 func NewState(o Output) State {
 	s := State{
 		out: o,
-		ctx: context.Background(),
-	}
-	s = dir("/")(s)
+	}.Dir("/")
 	s = s.ensurePlatform()
 	return s
 }
 
 type State struct {
-	out  Output
-	ctx  context.Context
-	opts []ConstraintsOpt
+	out   Output
+	prev  *State
+	key   interface{}
+	value func(context.Context) (interface{}, error)
+	opts  []ConstraintsOpt
+	async *asyncState
 }
 
 func (s State) ensurePlatform() State {
@@ -57,14 +58,48 @@ func (s State) ensurePlatform() State {
 }
 
 func (s State) WithValue(k, v interface{}) State {
+	return s.withValue(k, func(context.Context) (interface{}, error) {
+		return v, nil
+	})
+}
+
+func (s State) withValue(k interface{}, v func(context.Context) (interface{}, error)) State {
 	return State{
-		out: s.out,
-		ctx: context.WithValue(s.ctx, k, v),
+		out:   s.Output(),
+		prev:  &s, // doesn't need to be original pointer
+		key:   k,
+		value: v,
+	}
+}
+
+func (s State) Value(ctx context.Context, k interface{}) (interface{}, error) {
+	return s.getValue(k)(ctx)
+}
+
+func (s State) getValue(k interface{}) func(context.Context) (interface{}, error) {
+	if s.key == k {
+		return s.value
+	}
+	if s.async != nil {
+		return func(ctx context.Context) (interface{}, error) {
+			err := s.async.Do(ctx)
+			if err != nil {
+				return nil, err
+			}
+			return s.async.target.getValue(k)(ctx)
+		}
+	}
+	if s.prev == nil {
+		return nilValue
 	}
+	return s.prev.getValue(k)
 }
 
-func (s State) Value(k interface{}) interface{} {
-	return s.ctx.Value(k)
+func (s State) Async(f func(context.Context, State) (State, error)) State {
+	s2 := State{
+		async: &asyncState{f: f, prev: s},
+	}
+	return s2
 }
 
 func (s State) SetMarshalDefaults(co ...ConstraintsOpt) State {
@@ -72,11 +107,11 @@ func (s State) SetMarshalDefaults(co ...ConstraintsOpt) State {
 	return s
 }
 
-func (s State) Marshal(co ...ConstraintsOpt) (*Definition, error) {
+func (s State) Marshal(ctx context.Context, co ...ConstraintsOpt) (*Definition, error) {
 	def := &Definition{
 		Metadata: make(map[digest.Digest]pb.OpMetadata, 0),
 	}
-	if s.Output() == nil {
+	if s.Output() == nil || s.Output().Vertex(ctx) == nil {
 		return def, nil
 	}
 
@@ -89,11 +124,11 @@ func (s State) Marshal(co ...ConstraintsOpt) (*Definition, error) {
 		o.SetConstraintsOption(c)
 	}
 
-	def, err := marshal(s.Output().Vertex(), def, map[digest.Digest]struct{}{}, map[Vertex]struct{}{}, c)
+	def, err := marshal(ctx, s.Output().Vertex(ctx), def, map[digest.Digest]struct{}{}, map[Vertex]struct{}{}, c)
 	if err != nil {
 		return def, err
 	}
-	inp, err := s.Output().ToInput(c)
+	inp, err := s.Output().ToInput(ctx, c)
 	if err != nil {
 		return def, err
 	}
@@ -128,19 +163,19 @@ func (s State) Marshal(co ...ConstraintsOpt) (*Definition, error) {
 	return def, nil
 }
 
-func marshal(v Vertex, def *Definition, cache map[digest.Digest]struct{}, vertexCache map[Vertex]struct{}, c *Constraints) (*Definition, error) {
+func marshal(ctx context.Context, v Vertex, def *Definition, cache map[digest.Digest]struct{}, vertexCache map[Vertex]struct{}, c *Constraints) (*Definition, error) {
 	if _, ok := vertexCache[v]; ok {
 		return def, nil
 	}
 	for _, inp := range v.Inputs() {
 		var err error
-		def, err = marshal(inp.Vertex(), def, cache, vertexCache, c)
+		def, err = marshal(ctx, inp.Vertex(ctx), def, cache, vertexCache, c)
 		if err != nil {
 			return def, err
 		}
 	}
 
-	dgst, dt, opMeta, err := v.Marshal(c)
+	dgst, dt, opMeta, err := v.Marshal(ctx, c)
 	if err != nil {
 		return def, err
 	}
@@ -156,18 +191,22 @@ func marshal(v Vertex, def *Definition, cache map[digest.Digest]struct{}, vertex
 	return def, nil
 }
 
-func (s State) Validate() error {
-	return s.Output().Vertex().Validate()
+func (s State) Validate(ctx context.Context) error {
+	return s.Output().Vertex(ctx).Validate(ctx)
 }
 
 func (s State) Output() Output {
+	if s.async != nil {
+		return s.async.Output()
+	}
 	return s.out
 }
 
 func (s State) WithOutput(o Output) State {
+	prev := s
 	s = State{
-		out: o,
-		ctx: s.ctx,
+		out:  o,
+		prev: &prev,
 	}
 	s = s.ensurePlatform()
 	return s
@@ -200,24 +239,10 @@ func (s State) WithImageConfig(c []byte) (State, error) {
 
 func (s State) Run(ro ...RunOption) ExecState {
 	ei := &ExecInfo{State: s}
-	if p := s.GetPlatform(); p != nil {
-		ei.Constraints.Platform = p
-	}
 	for _, o := range ro {
 		o.SetRunOption(ei)
 	}
-	meta := Meta{
-		Args:       getArgs(ei.State),
-		Cwd:        getDir(ei.State),
-		Env:        getEnv(ei.State),
-		User:       getUser(ei.State),
-		ProxyEnv:   ei.ProxyEnv,
-		ExtraHosts: getExtraHosts(ei.State),
-		Network:    getNetwork(ei.State),
-		Security:   getSecurity(ei.State),
-	}
-
-	exec := NewExecOp(s.Output(), meta, ei.ReadonlyRootFS, ei.Constraints)
+	exec := NewExecOp(ei.State, ei.ProxyEnv, ei.ReadonlyRootFS, ei.Constraints)
 	for _, m := range ei.Mounts {
 		exec.AddMount(m.Target, m.Source, m.Opts...)
 	}
@@ -240,65 +265,74 @@ func (s State) File(a *FileAction, opts ...ConstraintsOpt) State {
 }
 
 func (s State) AddEnv(key, value string) State {
-	return addEnvf(key, value, false)(s)
+	return AddEnv(key, value)(s)
 }
 
 func (s State) AddEnvf(key, value string, v ...interface{}) State {
-	return addEnvf(key, value, true, v...)(s)
+	return AddEnvf(key, value, v...)(s)
 }
 
 func (s State) Dir(str string) State {
-	return dirf(str, false)(s)
+	return Dir(str)(s)
 }
 func (s State) Dirf(str string, v ...interface{}) State {
-	return dirf(str, true, v...)(s)
+	return Dirf(str, v...)(s)
 }
 
-func (s State) GetEnv(key string) (string, bool) {
-	return getEnv(s).Get(key)
+func (s State) GetEnv(ctx context.Context, key string) (string, bool, error) {
+	env, err := getEnv(s)(ctx)
+	if err != nil {
+		return "", false, err
+	}
+	v, ok := env.Get(key)
+	return v, ok, nil
 }
 
-func (s State) Env() []string {
-	return getEnv(s).ToArray()
+func (s State) Env(ctx context.Context) ([]string, error) {
+	env, err := getEnv(s)(ctx)
+	if err != nil {
+		return nil, err
+	}
+	return env.ToArray(), nil
 }
 
-func (s State) GetDir() string {
-	return getDir(s)
+func (s State) GetDir(ctx context.Context) (string, error) {
+	return getDir(s)(ctx)
 }
 
-func (s State) GetArgs() []string {
-	return getArgs(s)
+func (s State) GetArgs(ctx context.Context) ([]string, error) {
+	return getArgs(s)(ctx)
 }
 
 func (s State) Reset(s2 State) State {
-	return reset(s2)(s)
+	return Reset(s2)(s)
 }
 
 func (s State) User(v string) State {
-	return user(v)(s)
+	return User(v)(s)
 }
 
 func (s State) Platform(p specs.Platform) State {
 	return platform(p)(s)
 }
 
-func (s State) GetPlatform() *specs.Platform {
-	return getPlatform(s)
+func (s State) GetPlatform(ctx context.Context) (*specs.Platform, error) {
+	return getPlatform(s)(ctx)
 }
 
 func (s State) Network(n pb.NetMode) State {
-	return network(n)(s)
+	return Network(n)(s)
 }
 
-func (s State) GetNetwork() pb.NetMode {
-	return getNetwork(s)
+func (s State) GetNetwork(ctx context.Context) (pb.NetMode, error) {
+	return getNetwork(s)(ctx)
 }
 func (s State) Security(n pb.SecurityMode) State {
-	return security(n)(s)
+	return Security(n)(s)
 }
 
-func (s State) GetSecurity() pb.SecurityMode {
-	return getSecurity(s)
+func (s State) GetSecurity(ctx context.Context) (pb.SecurityMode, error) {
+	return getSecurity(s)(ctx)
 }
 
 func (s State) With(so ...StateOption) State {
@@ -321,7 +355,7 @@ type output struct {
 	platform *specs.Platform
 }
 
-func (o *output) ToInput(c *Constraints) (*pb.Input, error) {
+func (o *output) ToInput(ctx context.Context, c *Constraints) (*pb.Input, error) {
 	if o.err != nil {
 		return nil, o.err
 	}
@@ -333,14 +367,14 @@ func (o *output) ToInput(c *Constraints) (*pb.Input, error) {
 			return nil, err
 		}
 	}
-	dgst, _, _, err := o.vertex.Marshal(c)
+	dgst, _, _, err := o.vertex.Marshal(ctx, c)
 	if err != nil {
 		return nil, err
 	}
 	return &pb.Input{Digest: dgst, Index: index}, nil
 }
 
-func (o *output) Vertex() Vertex {
+func (o *output) Vertex(context.Context) Vertex {
 	return o.vertex
 }
 
@@ -513,3 +547,7 @@ func Require(filters ...string) ConstraintsOpt {
 		}
 	})
 }
+
+func nilValue(context.Context) (interface{}, error) {
+	return nil, nil
+}

+ 9 - 10
vendor/github.com/moby/buildkit/client/solve.go

@@ -115,6 +115,12 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG
 	}
 
 	var ex ExportEntry
+	if len(opt.Exports) > 1 {
+		return nil, errors.New("currently only single Exports can be specified")
+	}
+	if len(opt.Exports) == 1 {
+		ex = opt.Exports[0]
+	}
 
 	if !opt.SessionPreInitialized {
 		if len(syncedDirs) > 0 {
@@ -125,13 +131,6 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG
 			s.Allow(a)
 		}
 
-		if len(opt.Exports) > 1 {
-			return nil, errors.New("currently only single Exports can be specified")
-		}
-		if len(opt.Exports) == 1 {
-			ex = opt.Exports[0]
-		}
-
 		switch ex.Type {
 		case ExporterLocal:
 			if ex.Output != nil {
@@ -192,7 +191,7 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG
 
 		frontendInputs := make(map[string]*pb.Definition)
 		for key, st := range opt.FrontendInputs {
-			def, err := st.Marshal()
+			def, err := st.Marshal(ctx)
 			if err != nil {
 				return err
 			}
@@ -435,13 +434,13 @@ func parseCacheOptions(opt SolveOpt) (*cacheOptions, error) {
 					continue
 				}
 				for _, m := range idx.Manifests {
-					if m.Annotations[ocispec.AnnotationRefName] == "latest" {
+					if (m.Annotations[ocispec.AnnotationRefName] == "latest" && attrs["tag"] == "") || (attrs["tag"] != "" && m.Annotations[ocispec.AnnotationRefName] == attrs["tag"]) {
 						attrs["digest"] = string(m.Digest)
 						break
 					}
 				}
 				if attrs["digest"] == "" {
-					return nil, errors.New("local cache importer requires either explicit digest or \"latest\" tag on index.json")
+					return nil, errors.New("local cache importer requires either explicit digest, \"latest\" tag or custom tag on index.json")
 				}
 			}
 			contentStores["local:"+csDir] = cs

+ 105 - 0
vendor/github.com/moby/buildkit/cmd/buildkitd/config/config.go

@@ -0,0 +1,105 @@
+package config
+
+// Config provides containerd configuration data for the server
+type Config struct {
+	Debug bool `toml:"debug"`
+
+	// Root is the path to a directory where buildkit will store persistent data
+	Root string `toml:"root"`
+
+	//Entitlements e.g. security.insecure, network.host
+	Entitlements []string `toml:"insecure-entitlements"`
+	// GRPC configuration settings
+	GRPC GRPCConfig `toml:"grpc"`
+
+	Workers struct {
+		OCI        OCIConfig        `toml:"oci"`
+		Containerd ContainerdConfig `toml:"containerd"`
+	} `toml:"worker"`
+
+	Registries map[string]RegistryConfig `toml:"registry"`
+
+	DNS *DNSConfig `toml:"dns"`
+}
+
+type GRPCConfig struct {
+	Address      []string `toml:"address"`
+	DebugAddress string   `toml:"debugAddress"`
+	UID          int      `toml:"uid"`
+	GID          int      `toml:"gid"`
+
+	TLS TLSConfig `toml:"tls"`
+	// MaxRecvMsgSize int    `toml:"max_recv_message_size"`
+	// MaxSendMsgSize int    `toml:"max_send_message_size"`
+}
+
+type RegistryConfig struct {
+	Mirrors      []string     `toml:"mirrors"`
+	PlainHTTP    *bool        `toml:"http"`
+	Insecure     *bool        `toml:"insecure"`
+	RootCAs      []string     `toml:"ca"`
+	KeyPairs     []TLSKeyPair `toml:"keypair"`
+	TLSConfigDir []string     `toml:"tlsconfigdir"`
+}
+
+type TLSKeyPair struct {
+	Key         string `toml:"key"`
+	Certificate string `toml:"cert"`
+}
+
+type TLSConfig struct {
+	Cert string `toml:"cert"`
+	Key  string `toml:"key"`
+	CA   string `toml:"ca"`
+}
+
+type GCConfig struct {
+	GC            *bool      `toml:"gc"`
+	GCKeepStorage int64      `toml:"gckeepstorage"`
+	GCPolicy      []GCPolicy `toml:"gcpolicy"`
+}
+
+type NetworkConfig struct {
+	Mode          string `toml:"networkMode"`
+	CNIConfigPath string `toml:"cniConfigPath"`
+	CNIBinaryPath string `toml:"cniBinaryPath"`
+}
+
+type OCIConfig struct {
+	Enabled          *bool             `toml:"enabled"`
+	Labels           map[string]string `toml:"labels"`
+	Platforms        []string          `toml:"platforms"`
+	Snapshotter      string            `toml:"snapshotter"`
+	Rootless         bool              `toml:"rootless"`
+	NoProcessSandbox bool              `toml:"noProcessSandbox"`
+	GCConfig
+	NetworkConfig
+	// UserRemapUnsupported is unsupported key for testing. The feature is
+	// incomplete and the intention is to make it default without config.
+	UserRemapUnsupported string `toml:"userRemapUnsupported"`
+	// For use in storing the OCI worker binary name that will replace buildkit-runc
+	Binary string `toml:"binary"`
+}
+
+type ContainerdConfig struct {
+	Address   string            `toml:"address"`
+	Enabled   *bool             `toml:"enabled"`
+	Labels    map[string]string `toml:"labels"`
+	Platforms []string          `toml:"platforms"`
+	Namespace string            `toml:"namespace"`
+	GCConfig
+	NetworkConfig
+}
+
+type GCPolicy struct {
+	All          bool     `toml:"all"`
+	KeepBytes    int64    `toml:"keepBytes"`
+	KeepDuration int64    `toml:"keepDuration"`
+	Filters      []string `toml:"filters"`
+}
+
+type DNSConfig struct {
+	Nameservers   []string `toml:"nameservers"`
+	Options       []string `toml:"options"`
+	SearchDomains []string `toml:"searchDomains"`
+}

+ 31 - 0
vendor/github.com/moby/buildkit/cmd/buildkitd/config/gcpolicy.go

@@ -0,0 +1,31 @@
+package config
+
+const defaultCap int64 = 2e9 // 2GB
+
+func DefaultGCPolicy(p string, keep int64) []GCPolicy {
+	if keep == 0 {
+		keep = DetectDefaultGCCap(p)
+	}
+	return []GCPolicy{
+		// if build cache uses more than 512MB delete the most easily reproducible data after it has not been used for 2 days
+		{
+			Filters:      []string{"type==source.local,type==exec.cachemount,type==source.git.checkout"},
+			KeepDuration: 48 * 3600, // 48h
+			KeepBytes:    512 * 1e6, // 512MB
+		},
+		// remove any data not used for 60 days
+		{
+			KeepDuration: 60 * 24 * 3600, // 60d
+			KeepBytes:    keep,
+		},
+		// keep the unshared build cache under cap
+		{
+			KeepBytes: keep,
+		},
+		// if previous policies were insufficient start deleting internal data to keep build cache under cap
+		{
+			All:       true,
+			KeepBytes: keep,
+		},
+	}
+}

+ 17 - 0
vendor/github.com/moby/buildkit/cmd/buildkitd/config/gcpolicy_unix.go

@@ -0,0 +1,17 @@
+// +build !windows
+
+package config
+
+import (
+	"syscall"
+)
+
+func DetectDefaultGCCap(root string) int64 {
+	var st syscall.Statfs_t
+	if err := syscall.Statfs(root, &st); err != nil {
+		return defaultCap
+	}
+	diskSize := int64(st.Bsize) * int64(st.Blocks)
+	avail := diskSize / 10
+	return (avail/(1<<30) + 1) * 1e9 // round up
+}

+ 7 - 0
vendor/github.com/moby/buildkit/cmd/buildkitd/config/gcpolicy_windows.go

@@ -0,0 +1,7 @@
+// +build windows
+
+package config
+
+func DetectDefaultGCCap(root string) int64 {
+	return defaultCap
+}

+ 26 - 6
vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go

@@ -139,7 +139,7 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
 		buildContext = st
 	} else if httpPrefix.MatchString(opts[localNameContext]) {
 		httpContext := llb.HTTP(opts[localNameContext], llb.Filename("context"), dockerfile2llb.WithInternalName("load remote build context"))
-		def, err := httpContext.Marshal(marshalOpts...)
+		def, err := httpContext.Marshal(ctx, marshalOpts...)
 		if err != nil {
 			return nil, errors.Wrapf(err, "failed to marshal httpcontext")
 		}
@@ -221,7 +221,7 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
 		}
 	}
 
-	def, err := src.Marshal(marshalOpts...)
+	def, err := src.Marshal(ctx, marshalOpts...)
 	if err != nil {
 		return nil, errors.Wrapf(err, "failed to marshal local source")
 	}
@@ -271,7 +271,7 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
 				)
 				dockerignoreState = &st
 			}
-			def, err := dockerignoreState.Marshal(marshalOpts...)
+			def, err := dockerignoreState.Marshal(ctx, marshalOpts...)
 			if err != nil {
 				return err
 			}
@@ -363,7 +363,7 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
 					return errors.Wrapf(err, "failed to create LLB definition")
 				}
 
-				def, err := st.Marshal()
+				def, err := st.Marshal(ctx)
 				if err != nil {
 					return errors.Wrapf(err, "failed to marshal LLB definition")
 				}
@@ -456,9 +456,29 @@ func forwardGateway(ctx context.Context, c client.Client, ref string, cmdline st
 	}
 	opts["cmdline"] = cmdline
 	opts["source"] = ref
+
+	gwcaps := c.BuildOpts().Caps
+	var frontendInputs map[string]*pb.Definition
+	if (&gwcaps).Supports(gwpb.CapFrontendInputs) == nil {
+		inputs, err := c.Inputs(ctx)
+		if err != nil {
+			return nil, errors.Wrapf(err, "failed to get frontend inputs")
+		}
+
+		frontendInputs = make(map[string]*pb.Definition)
+		for name, state := range inputs {
+			def, err := state.Marshal(ctx)
+			if err != nil {
+				return nil, err
+			}
+			frontendInputs[name] = def.ToPB()
+		}
+	}
+
 	return c.Solve(ctx, client.SolveRequest{
-		Frontend:    "gateway.v0",
-		FrontendOpt: opts,
+		Frontend:       "gateway.v0",
+		FrontendOpt:    opts,
+		FrontendInputs: frontendInputs,
 	})
 }
 

+ 53 - 13
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go

@@ -462,7 +462,11 @@ type dispatchOpt struct {
 func dispatch(d *dispatchState, cmd command, opt dispatchOpt) error {
 	if ex, ok := cmd.Command.(instructions.SupportsSingleWordExpansion); ok {
 		err := ex.Expand(func(word string) (string, error) {
-			return opt.shlex.ProcessWord(word, d.state.Env())
+			env, err := d.state.Env(context.TODO())
+			if err != nil {
+				return "", err
+			}
+			return opt.shlex.ProcessWord(word, env)
 		})
 		if err != nil {
 			return err
@@ -626,7 +630,10 @@ func dispatchRun(d *dispatchState, c *instructions.RunCommand, proxy *llb.ProxyE
 	if c.PrependShell {
 		args = withShell(d.image, args)
 	}
-	env := d.state.Env()
+	env, err := d.state.Env(context.TODO())
+	if err != nil {
+		return err
+	}
 	opt := []llb.RunOption{llb.Args(args), dfCmd(c)}
 	if d.ignoreCache {
 		opt = append(opt, llb.IgnoreCache)
@@ -661,7 +668,11 @@ func dispatchRun(d *dispatchState, c *instructions.RunCommand, proxy *llb.ProxyE
 	shlex.RawQuotes = true
 	shlex.SkipUnsetEnv = true
 
-	opt = append(opt, llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(&shlex, c.String(), env)), d.prefixPlatform, d.state.GetPlatform())))
+	pl, err := d.state.GetPlatform(context.TODO())
+	if err != nil {
+		return err
+	}
+	opt = append(opt, llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(&shlex, c.String(), env)), d.prefixPlatform, pl)))
 	for _, h := range dopt.extraHosts {
 		opt = append(opt, llb.AddExtraHost(h.Host, h.IP))
 	}
@@ -687,7 +698,11 @@ func dispatchWorkdir(d *dispatchState, c *instructions.WorkdirCommand, commit bo
 			if d.platform != nil {
 				platform = *d.platform
 			}
-			d.state = d.state.File(llb.Mkdir(wd, 0755, mkdirOpt...), llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(opt.shlex, c.String(), d.state.Env())), d.prefixPlatform, &platform)))
+			env, err := d.state.Env(context.TODO())
+			if err != nil {
+				return err
+			}
+			d.state = d.state.File(llb.Mkdir(wd, 0755, mkdirOpt...), llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(opt.shlex, c.String(), env)), d.prefixPlatform, &platform)))
 			withLayer = true
 		}
 		return commitToHistory(&d.image, "WORKDIR "+wd, withLayer, nil)
@@ -696,7 +711,11 @@ func dispatchWorkdir(d *dispatchState, c *instructions.WorkdirCommand, commit bo
 }
 
 func dispatchCopyFileOp(d *dispatchState, c instructions.SourcesAndDest, sourceState llb.State, isAddCommand bool, cmdToPrint fmt.Stringer, chown string, opt dispatchOpt) error {
-	dest := path.Join("/", pathRelativeToWorkingDir(d.state, c.Dest()))
+	pp, err := pathRelativeToWorkingDir(d.state, c.Dest())
+	if err != nil {
+		return err
+	}
+	dest := path.Join("/", pp)
 	if c.Dest() == "." || c.Dest() == "" || c.Dest()[len(c.Dest())-1] == filepath.Separator {
 		dest += string(filepath.Separator)
 	}
@@ -772,7 +791,12 @@ func dispatchCopyFileOp(d *dispatchState, c instructions.SourcesAndDest, sourceS
 		platform = *d.platform
 	}
 
-	fileOpt := []llb.ConstraintsOpt{llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(opt.shlex, cmdToPrint.String(), d.state.Env())), d.prefixPlatform, &platform))}
+	env, err := d.state.Env(context.TODO())
+	if err != nil {
+		return err
+	}
+
+	fileOpt := []llb.ConstraintsOpt{llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(opt.shlex, cmdToPrint.String(), env)), d.prefixPlatform, &platform))}
 	if d.ignoreCache {
 		fileOpt = append(fileOpt, llb.IgnoreCache)
 	}
@@ -787,8 +811,11 @@ func dispatchCopy(d *dispatchState, c instructions.SourcesAndDest, sourceState l
 	}
 
 	img := llb.Image(opt.copyImage, llb.MarkImageInternal, llb.Platform(opt.buildPlatforms[0]), WithInternalName("helper image for file operations"))
-
-	dest := path.Join(".", pathRelativeToWorkingDir(d.state, c.Dest()))
+	pp, err := pathRelativeToWorkingDir(d.state, c.Dest())
+	if err != nil {
+		return err
+	}
+	dest := path.Join(".", pp)
 	if c.Dest() == "." || c.Dest() == "" || c.Dest()[len(c.Dest())-1] == filepath.Separator {
 		dest += string(filepath.Separator)
 	}
@@ -861,7 +888,12 @@ func dispatchCopy(d *dispatchState, c instructions.SourcesAndDest, sourceState l
 		platform = *d.platform
 	}
 
-	runOpt := []llb.RunOption{llb.Args(args), llb.Dir("/dest"), llb.ReadonlyRootFS(), dfCmd(cmdToPrint), llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(opt.shlex, cmdToPrint.String(), d.state.Env())), d.prefixPlatform, &platform))}
+	env, err := d.state.Env(context.TODO())
+	if err != nil {
+		return err
+	}
+
+	runOpt := []llb.RunOption{llb.Args(args), llb.Dir("/dest"), llb.ReadonlyRootFS(), dfCmd(cmdToPrint), llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(opt.shlex, cmdToPrint.String(), env)), d.prefixPlatform, &platform))}
 	if d.ignoreCache {
 		runOpt = append(runOpt, llb.IgnoreCache)
 	}
@@ -936,8 +968,12 @@ func dispatchHealthcheck(d *dispatchState, c *instructions.HealthCheckCommand) e
 
 func dispatchExpose(d *dispatchState, c *instructions.ExposeCommand, shlex *shell.Lex) error {
 	ports := []string{}
+	env, err := d.state.Env(context.TODO())
+	if err != nil {
+		return err
+	}
 	for _, p := range c.Ports {
-		ps, err := shlex.ProcessWords(p, d.state.Env())
+		ps, err := shlex.ProcessWords(p, env)
 		if err != nil {
 			return err
 		}
@@ -1018,11 +1054,15 @@ func dispatchArg(d *dispatchState, c *instructions.ArgCommand, metaArgs []instru
 	return commitToHistory(&d.image, commitStr, false, nil)
 }
 
-func pathRelativeToWorkingDir(s llb.State, p string) string {
+func pathRelativeToWorkingDir(s llb.State, p string) (string, error) {
 	if path.IsAbs(p) {
-		return p
+		return p, nil
+	}
+	dir, err := s.GetDir(context.TODO())
+	if err != nil {
+		return "", err
 	}
-	return path.Join(s.GetDir(), p)
+	return path.Join(dir, p), nil
 }
 
 func splitWildcards(name string) (string, string) {

+ 6 - 1
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_runmount.go

@@ -3,6 +3,7 @@
 package dockerfile2llb
 
 import (
+	"context"
 	"fmt"
 	"os"
 	"path"
@@ -132,7 +133,11 @@ func dispatchRunMounts(d *dispatchState, c *instructions.RunCommand, sources []*
 		}
 		target := mount.Target
 		if !filepath.IsAbs(filepath.Clean(mount.Target)) {
-			target = filepath.Join("/", d.state.GetDir(), mount.Target)
+			dir, err := d.state.GetDir(context.TODO())
+			if err != nil {
+				return nil, err
+			}
+			target = filepath.Join("/", dir, mount.Target)
 		}
 		if target == "/" {
 			return nil, errors.Errorf("invalid mount target %q", target)

+ 1 - 1
vendor/github.com/moby/buildkit/frontend/gateway/gateway.go

@@ -135,7 +135,7 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten
 
 		src := llb.Image(sourceRef.String(), &markTypeFrontend{})
 
-		def, err := src.Marshal()
+		def, err := src.Marshal(ctx)
 		if err != nil {
 			return nil, err
 		}

+ 3 - 3
vendor/github.com/moby/buildkit/go.mod

@@ -3,6 +3,7 @@ module github.com/moby/buildkit
 go 1.13
 
 require (
+	github.com/AkihiroSuda/containerd-fuse-overlayfs v0.0.0-20200220082720-bb896865146c
 	github.com/BurntSushi/toml v0.3.1
 	github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5
 	github.com/Microsoft/hcsshim v0.8.7 // indirect
@@ -23,13 +24,12 @@ require (
 	github.com/docker/docker v0.0.0
 	github.com/docker/docker-credential-helpers v0.6.0 // indirect
 	github.com/docker/go-connections v0.3.0
-	github.com/docker/go-events v0.0.0-20170721190031-9461782956ad // indirect
 	github.com/docker/libnetwork v0.8.0-dev.2.0.20200226230617-d8334ccdb9be
 	github.com/gofrs/flock v0.7.0
 	github.com/gogo/googleapis v1.3.2
 	github.com/gogo/protobuf v1.3.1
 	github.com/golang/protobuf v1.3.3
-	github.com/google/go-cmp v0.3.0
+	github.com/google/go-cmp v0.3.1
 	github.com/google/shlex v0.0.0-20150127133951-6f45313302b9
 	github.com/google/uuid v1.1.1 // indirect
 	github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645
@@ -54,7 +54,7 @@ require (
 	github.com/sirupsen/logrus v1.4.2
 	github.com/stretchr/testify v1.4.0
 	github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 // indirect
-	github.com/tonistiigi/fsutil v0.0.0-20200225063759-013a9fe6aee2
+	github.com/tonistiigi/fsutil v0.0.0-20200326231323-c2c7d7b0e144
 	github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea
 	github.com/uber/jaeger-client-go v0.0.0-20180103221425-e02c85f9069e
 	github.com/uber/jaeger-lib v1.2.1 // indirect

+ 7 - 3
vendor/github.com/moby/buildkit/solver/cachemanager.go

@@ -150,8 +150,12 @@ type LoadedResult struct {
 	CacheKey    *CacheKey
 }
 
-func (c *cacheManager) filterResults(m map[string]Result, ck *CacheKey) (results []LoadedResult, err error) {
+func (c *cacheManager) filterResults(m map[string]Result, ck *CacheKey, visited map[string]struct{}) (results []LoadedResult, err error) {
 	id := c.getID(ck)
+	if _, ok := visited[id]; ok {
+		return nil, nil
+	}
+	visited[id] = struct{}{}
 	if err := c.backend.WalkResults(id, func(cr CacheResult) error {
 		res, ok := m[id]
 		if ok {
@@ -170,7 +174,7 @@ func (c *cacheManager) filterResults(m map[string]Result, ck *CacheKey) (results
 	}
 	for _, keys := range ck.Deps() {
 		for _, key := range keys {
-			res, err := c.filterResults(m, key.CacheKey.CacheKey)
+			res, err := c.filterResults(m, key.CacheKey.CacheKey, visited)
 			if err != nil {
 				for _, r := range results {
 					r.Result.Release(context.TODO())
@@ -207,7 +211,7 @@ func (c *cacheManager) LoadWithParents(ctx context.Context, rec *CacheRecord) ([
 		return nil, err
 	}
 
-	results, err := c.filterResults(m, rec.key)
+	results, err := c.filterResults(m, rec.key, map[string]struct{}{})
 	if err != nil {
 		for _, r := range m {
 			r.Release(context.TODO())

+ 6 - 3
vendor/github.com/moby/buildkit/solver/exporter.go

@@ -20,11 +20,12 @@ func addBacklinks(t CacheExporterTarget, rec CacheExporterRecord, cm *cacheManag
 	if rec == nil {
 		var ok bool
 		rec, ok = bkm[id]
-		if ok {
+		if ok && rec != nil {
 			return rec, nil
 		}
 		_ = ok
 	}
+	bkm[id] = nil
 	if err := cm.backend.WalkBacklinks(id, func(id string, link CacheInfoLink) error {
 		if rec == nil {
 			rec = t.Add(link.Digest)
@@ -37,7 +38,9 @@ func addBacklinks(t CacheExporterTarget, rec CacheExporterRecord, cm *cacheManag
 				return err
 			}
 		}
-		rec.LinkFrom(r, int(link.Input), link.Selector.String())
+		if r != nil {
+			rec.LinkFrom(r, int(link.Input), link.Selector.String())
+		}
 		return nil
 	}); err != nil {
 		return nil, err
@@ -66,6 +69,7 @@ func (e *exporter) ExportTo(ctx context.Context, t CacheExporterTarget, opt Cach
 	if t.Visited(e) {
 		return e.res, nil
 	}
+	t.Visit(e)
 
 	deps := e.k.Deps()
 
@@ -177,7 +181,6 @@ func (e *exporter) ExportTo(ctx context.Context, t CacheExporterTarget, opt Cach
 	}
 
 	e.res = allRec
-	t.Visit(e)
 
 	return e.res, nil
 }

+ 3 - 2
vendor/github.com/moby/buildkit/source/git/gitsource.go

@@ -272,8 +272,9 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context) (out cache.ImmutableRe
 		}
 		args = append(args, "origin")
 		if !isCommitSHA(ref) {
-			args = append(args, ref+":tags/"+ref)
-			// local refs are needed so they would be advertised on next fetches
+			args = append(args, "--force", ref+":tags/"+ref)
+			// local refs are needed so they would be advertised on next fetches. Force is used
+			// in case the ref is a branch and it now points to a different commit sha
 			// TODO: is there a better way to do this?
 		}
 		if _, err := gitWithinDir(ctx, gitDir, "", args...); err != nil {

+ 193 - 28
vendor/github.com/moby/buildkit/util/resolver/resolver.go

@@ -1,54 +1,219 @@
 package resolver
 
 import (
-	"math/rand"
+	"context"
+	"crypto/tls"
+	"crypto/x509"
+	"io/ioutil"
+	"net"
+	"net/http"
+	"os"
+	"path/filepath"
+	"runtime"
 	"strings"
+	"time"
 
+	"github.com/containerd/containerd/remotes"
 	"github.com/containerd/containerd/remotes/docker"
-	"github.com/docker/distribution/reference"
+	"github.com/moby/buildkit/cmd/buildkitd/config"
+	"github.com/moby/buildkit/session"
+	"github.com/moby/buildkit/session/auth"
 	"github.com/moby/buildkit/util/tracing"
+	"github.com/pkg/errors"
 )
 
-type RegistryConf struct {
-	Mirrors   []string
-	PlainHTTP *bool
+func fillInsecureOpts(host string, c config.RegistryConfig, h *docker.RegistryHost) error {
+	tc, err := loadTLSConfig(c)
+	if err != nil {
+		return err
+	}
+
+	if c.PlainHTTP != nil && *c.PlainHTTP {
+		h.Scheme = "http"
+	} else if c.Insecure != nil && *c.Insecure {
+		tc.InsecureSkipVerify = true
+	} else if c.PlainHTTP == nil {
+		if ok, _ := docker.MatchLocalhost(host); ok {
+			h.Scheme = "http"
+		}
+	}
+
+	transport := newDefaultTransport()
+	transport.TLSClientConfig = tc
+
+	h.Client = &http.Client{
+		Transport: tracing.NewTransport(transport),
+	}
+	return nil
 }
 
-type ResolveOptionsFunc func(string) docker.ResolverOptions
+func loadTLSConfig(c config.RegistryConfig) (*tls.Config, error) {
+	for _, d := range c.TLSConfigDir {
+		fs, err := ioutil.ReadDir(d)
+		if err != nil && !os.IsNotExist(err) && !os.IsPermission(err) {
+			return nil, errors.WithStack(err)
+		}
+		for _, f := range fs {
+			if strings.HasSuffix(f.Name(), ".crt") {
+				c.RootCAs = append(c.RootCAs, filepath.Join(d, f.Name()))
+			}
+			if strings.HasSuffix(f.Name(), ".cert") {
+				c.KeyPairs = append(c.KeyPairs, config.TLSKeyPair{
+					Certificate: filepath.Join(d, f.Name()),
+					Key:         filepath.Join(d, strings.TrimSuffix(f.Name(), ".cert")+".key"),
+				})
+			}
+		}
+	}
 
-func NewResolveOptionsFunc(m map[string]RegistryConf) ResolveOptionsFunc {
-	return func(ref string) docker.ResolverOptions {
-		def := docker.ResolverOptions{
-			Client: tracing.DefaultClient,
+	tc := &tls.Config{}
+	if len(c.RootCAs) > 0 {
+		systemPool, err := x509.SystemCertPool()
+		if err != nil {
+			if runtime.GOOS == "windows" {
+				systemPool = x509.NewCertPool()
+			} else {
+				return nil, errors.Wrapf(err, "unable to get system cert pool")
+			}
 		}
+		tc.RootCAs = systemPool
+	}
 
-		parsed, err := reference.ParseNormalizedNamed(ref)
+	for _, p := range c.RootCAs {
+		dt, err := ioutil.ReadFile(p)
 		if err != nil {
-			return def
+			return nil, errors.Wrapf(err, "failed to read %s", p)
 		}
-		host := reference.Domain(parsed)
+		tc.RootCAs.AppendCertsFromPEM(dt)
+	}
 
-		c, ok := m[host]
-		if !ok {
-			return def
+	for _, kp := range c.KeyPairs {
+		cert, err := tls.LoadX509KeyPair(kp.Certificate, kp.Key)
+		if err != nil {
+			return nil, errors.Wrapf(err, "failed to load keypair for %s", kp.Certificate)
 		}
+		tc.Certificates = append(tc.Certificates, cert)
+	}
+	return tc, nil
+}
 
-		var mirrorHost string
-		if len(c.Mirrors) > 0 {
-			mirrorHost = c.Mirrors[rand.Intn(len(c.Mirrors))]
-			def.Host = func(string) (string, error) {
-				return mirrorHost, nil
+func NewRegistryConfig(m map[string]config.RegistryConfig) docker.RegistryHosts {
+	return docker.Registries(
+		func(host string) ([]docker.RegistryHost, error) {
+			c, ok := m[host]
+			if !ok {
+				return nil, nil
+			}
+
+			var out []docker.RegistryHost
+
+			for _, mirror := range c.Mirrors {
+				h := docker.RegistryHost{
+					Scheme:       "https",
+					Client:       newDefaultClient(),
+					Host:         mirror,
+					Path:         "/v2",
+					Capabilities: docker.HostCapabilityPull | docker.HostCapabilityResolve,
+				}
+
+				if err := fillInsecureOpts(mirror, m[mirror], &h); err != nil {
+					return nil, err
+				}
+
+				out = append(out, h)
+			}
+
+			if host == "docker.io" {
+				host = "registry-1.docker.io"
 			}
-		}
 
-		if c.PlainHTTP != nil {
-			def.PlainHTTP = *c.PlainHTTP
-		} else {
-			if mirrorHost == "localhost" || strings.HasPrefix(mirrorHost, "localhost:") {
-				def.PlainHTTP = true
+			h := docker.RegistryHost{
+				Scheme:       "https",
+				Client:       newDefaultClient(),
+				Host:         host,
+				Path:         "/v2",
+				Capabilities: docker.HostCapabilityPush | docker.HostCapabilityPull | docker.HostCapabilityResolve,
 			}
+
+			if err := fillInsecureOpts(host, c, &h); err != nil {
+				return nil, err
+			}
+
+			out = append(out, h)
+			return out, nil
+		},
+		docker.ConfigureDefaultRegistries(
+			docker.WithClient(newDefaultClient()),
+			docker.WithPlainHTTP(docker.MatchLocalhost),
+		),
+	)
+}
+
+func New(ctx context.Context, hosts docker.RegistryHosts, sm *session.Manager) remotes.Resolver {
+	return docker.NewResolver(docker.ResolverOptions{
+		Hosts: hostsWithCredentials(ctx, hosts, sm),
+	})
+}
+
+func hostsWithCredentials(ctx context.Context, hosts docker.RegistryHosts, sm *session.Manager) docker.RegistryHosts {
+	id := session.FromContext(ctx)
+	if id == "" {
+		return hosts
+	}
+	return func(domain string) ([]docker.RegistryHost, error) {
+		res, err := hosts(domain)
+		if err != nil {
+			return nil, err
 		}
+		if len(res) == 0 {
+			return nil, nil
+		}
+
+		timeoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+		defer cancel()
+
+		caller, err := sm.Get(timeoutCtx, id)
+		if err != nil {
+			return nil, err
+		}
+
+		a := docker.NewDockerAuthorizer(
+			docker.WithAuthClient(res[0].Client),
+			docker.WithAuthCreds(auth.CredentialsFunc(context.TODO(), caller)),
+		)
+		for i := range res {
+			res[i].Authorizer = a
+		}
+		return res, nil
+	}
+}
+
+func newDefaultClient() *http.Client {
+	return &http.Client{
+		Transport: newDefaultTransport(),
+	}
+}
 
-		return def
+// newDefaultTransport is for pull or push client
+//
+// NOTE: For push, there must disable http2 for https because the flow control
+// will limit data transfer. The net/http package doesn't provide http2 tunable
+// settings which limits push performance.
+//
+// REF: https://github.com/golang/go/issues/14077
+func newDefaultTransport() *http.Transport {
+	return &http.Transport{
+		Proxy: http.ProxyFromEnvironment,
+		DialContext: (&net.Dialer{
+			Timeout:   30 * time.Second,
+			KeepAlive: 30 * time.Second,
+			DualStack: true,
+		}).DialContext,
+		MaxIdleConns:          10,
+		IdleConnTimeout:       30 * time.Second,
+		TLSHandshakeTimeout:   10 * time.Second,
+		ExpectContinueTimeout: 5 * time.Second,
+		DisableKeepAlives:     true,
+		TLSNextProto:          make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
 	}
 }

+ 6 - 0
vendor/github.com/moby/buildkit/util/tracing/tracing.go

@@ -74,6 +74,12 @@ type Transport struct {
 	http.RoundTripper
 }
 
+func NewTransport(rt http.RoundTripper) http.RoundTripper {
+	return &Transport{
+		RoundTripper: &nethttp.Transport{RoundTripper: rt},
+	}
+}
+
 func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
 	span := opentracing.SpanFromContext(req.Context())
 	if span == nil { // no tracer connected with either request or transport

+ 5 - 1
vendor/github.com/tonistiigi/fsutil/tarwriter.go

@@ -37,7 +37,11 @@ func WriteTar(ctx context.Context, fs FS, w io.Writer) error {
 		hdr.Linkname = stat.Linkname
 		if hdr.Linkname != "" {
 			hdr.Size = 0
-			hdr.Typeflag = tar.TypeLink
+			if fi.Mode() & os.ModeSymlink != 0 {
+				hdr.Typeflag = tar.TypeSymlink
+			} else {
+				hdr.Typeflag = tar.TypeLink
+			}
 		}
 
 		if len(stat.Xattrs) > 0 {