Browse code

vendor: update buildkit to d75ed2b68

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>

Tonis Tiigi authored on 2020/02/25 07:14:23
Showing 57 changed files
... ...
@@ -28,7 +28,7 @@ import (
28 28
 	pkgprogress "github.com/docker/docker/pkg/progress"
29 29
 	"github.com/docker/docker/reference"
30 30
 	"github.com/moby/buildkit/cache"
31
-	gw "github.com/moby/buildkit/frontend/gateway/client"
31
+	"github.com/moby/buildkit/client/llb"
32 32
 	"github.com/moby/buildkit/session"
33 33
 	"github.com/moby/buildkit/session/auth"
34 34
 	"github.com/moby/buildkit/source"
... ...
@@ -150,7 +150,7 @@ func (is *imageSource) resolveRemote(ctx context.Context, ref string, platform *
150 150
 	return typed.dgst, typed.dt, nil
151 151
 }
152 152
 
153
-func (is *imageSource) ResolveImageConfig(ctx context.Context, ref string, opt gw.ResolveImageConfigOpt, sm *session.Manager) (digest.Digest, []byte, error) {
153
+func (is *imageSource) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt, sm *session.Manager) (digest.Digest, []byte, error) {
154 154
 	resolveMode, err := source.ParseImageResolveMode(opt.ResolveMode)
155 155
 	if err != nil {
156 156
 		return "", nil, err
... ...
@@ -304,7 +304,7 @@ func (p *puller) resolve(ctx context.Context) error {
304 304
 				_ = resolveProgressDone(err)
305 305
 				return
306 306
 			}
307
-			_, dt, err := p.is.ResolveImageConfig(ctx, ref.String(), gw.ResolveImageConfigOpt{Platform: &p.platform, ResolveMode: resolveModeToString(p.src.ResolveMode)}, p.sm)
307
+			_, dt, err := p.is.ResolveImageConfig(ctx, ref.String(), llb.ResolveImageConfigOpt{Platform: &p.platform, ResolveMode: resolveModeToString(p.src.ResolveMode)}, p.sm)
308 308
 			if err != nil {
309 309
 				p.resolveErr = err
310 310
 				_ = resolveProgressDone(err)
... ...
@@ -23,12 +23,12 @@ import (
23 23
 	"github.com/moby/buildkit/cache"
24 24
 	"github.com/moby/buildkit/cache/metadata"
25 25
 	"github.com/moby/buildkit/client"
26
+	"github.com/moby/buildkit/client/llb"
26 27
 	"github.com/moby/buildkit/executor"
27 28
 	"github.com/moby/buildkit/exporter"
28 29
 	localexporter "github.com/moby/buildkit/exporter/local"
29 30
 	tarexporter "github.com/moby/buildkit/exporter/tar"
30 31
 	"github.com/moby/buildkit/frontend"
31
-	gw "github.com/moby/buildkit/frontend/gateway/client"
32 32
 	"github.com/moby/buildkit/session"
33 33
 	"github.com/moby/buildkit/snapshot"
34 34
 	"github.com/moby/buildkit/solver"
... ...
@@ -183,7 +183,7 @@ func (w *Worker) ResolveOp(v solver.Vertex, s frontend.FrontendLLBBridge, sm *se
183 183
 }
184 184
 
185 185
 // ResolveImageConfig returns image config for an image
186
-func (w *Worker) ResolveImageConfig(ctx context.Context, ref string, opt gw.ResolveImageConfigOpt, sm *session.Manager) (digest.Digest, []byte, error) {
186
+func (w *Worker) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt, sm *session.Manager) (digest.Digest, []byte, error) {
187 187
 	// ImageSource is typically source/containerimage
188 188
 	resolveImageConfig, ok := w.ImageSource.(resolveImageConfig)
189 189
 	if !ok {
... ...
@@ -477,7 +477,7 @@ func oneOffProgress(ctx context.Context, id string) func(err error) error {
477 477
 }
478 478
 
479 479
 type resolveImageConfig interface {
480
-	ResolveImageConfig(ctx context.Context, ref string, opt gw.ResolveImageConfigOpt, sm *session.Manager) (digest.Digest, []byte, error)
480
+	ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt, sm *session.Manager) (digest.Digest, []byte, error)
481 481
 }
482 482
 
483 483
 type emptyProvider struct {
... ...
@@ -26,8 +26,8 @@ github.com/imdario/mergo                            1afb36080aec31e0d1528973ebe6
26 26
 golang.org/x/sync                                   e225da77a7e68af35c70ccbf71af2b83e6acac3c
27 27
 
28 28
 # buildkit
29
-github.com/moby/buildkit                            4f4e03067523b2fc5ca2f17514a5e75ad63e02fb
30
-github.com/tonistiigi/fsutil                        0f039a052ca1da01626278199624b62aed9b3729
29
+github.com/moby/buildkit                            d75ed2b682485d4e4a35e46531230111424f8a65
30
+github.com/tonistiigi/fsutil                        6c909ab392c173a4264ae1bfcbc0450b9aac0c7d
31 31
 github.com/grpc-ecosystem/grpc-opentracing          8e809c8a86450a29b90dcc9efbf062d0fe6d9746
32 32
 github.com/opentracing/opentracing-go               1361b9cd60be79c4c3a7fa9841b3c132e40066a7
33 33
 github.com/google/shlex                             e7afc7fbc51079733e9468cdfd1efcd7d196cd1d
... ...
@@ -45,7 +45,7 @@ You don't need to read this document unless you want to use the full-featured st
45 45
     - [Building a Dockerfile using external frontend:](#building-a-dockerfile-using-external-frontend)
46 46
     - [Building a Dockerfile with experimental features like `RUN --mount=type=(bind|cache|tmpfs|secret|ssh)`](#building-a-dockerfile-with-experimental-features-like-run---mounttypebindcachetmpfssecretssh)
47 47
   - [Output](#output)
48
-    - [Registry](#registry)
48
+    - [Image/Registry](#imageregistry)
49 49
     - [Local directory](#local-directory)
50 50
     - [Docker tarball](#docker-tarball)
51 51
     - [OCI tarball](#oci-tarball)
... ...
@@ -85,6 +85,7 @@ BuildKit is used by the following projects:
85 85
 -   [Rio](https://github.com/rancher/rio)
86 86
 -   [PouchContainer](https://github.com/alibaba/pouch)
87 87
 -   [Docker buildx](https://github.com/docker/buildx)
88
+-   [Okteto Cloud](https://okteto.com/)
88 89
 
89 90
 ## Quick start
90 91
 
... ...
@@ -94,7 +95,7 @@ BuildKit is composed of the `buildkitd` daemon and the `buildctl` client.
94 94
 While the `buildctl` client is available for Linux, macOS, and Windows, the `buildkitd` daemon is only available for Linux currently.
95 95
 
96 96
 The `buildkitd` daemon requires the following components to be installed:
97
--   [runc](https://github.com/opencontainers/runc)
97
+-   [runc](https://github.com/opencontainers/runc) or [crun](https://github.com/containers/crun)
98 98
 -   [containerd](https://github.com/containerd/containerd) (if you want to use containerd worker)
99 99
 
100 100
 The latest binaries of BuildKit are available [here](https://github.com/moby/buildkit/releases) for Linux, macOS, and Windows.
... ...
@@ -125,6 +126,11 @@ We are open to adding more backends.
125 125
 The buildkitd daemon listens gRPC API on `/run/buildkit/buildkitd.sock` by default, but you can also use TCP sockets.
126 126
 See [Expose BuildKit as a TCP service](#expose-buildkit-as-a-tcp-service).
127 127
 
128
+:information_source: Notice to Fedora 31 users:
129
+
130
+* 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` .
131
+* 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.
132
+
128 133
 ### Exploring LLB
129 134
 
130 135
 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.
... ...
@@ -193,7 +199,7 @@ See [`frontend/dockerfile/docs/experimental.md`](frontend/dockerfile/docs/experi
193 193
 
194 194
 By default, the build result and intermediate cache will only remain internally in BuildKit. An output needs to be specified to retrieve the result.
195 195
 
196
-#### Registry
196
+#### Image/Registry
197 197
 
198 198
 ```bash
199 199
 buildctl build ... --output type=image,name=docker.io/username/image,push=true
... ...
@@ -209,6 +215,18 @@ buildctl build ...\
209 209
   --import-cache type=registry,ref=docker.io/username/image
210 210
 ```
211 211
 
212
+Keys supported by image output:
213
+* `name=[value]`: image name
214
+* `push=true`: push after creating the image
215
+* `push-by-digest=true`: push unnamed image
216
+* `registry.insecure=true`: push to insecure HTTP registry
217
+* `oci-mediatypes=true`: use OCI mediatypes in configuration JSON instead of Docker's
218
+* `unpack=true`: unpack image after creation (for use with containerd)
219
+* `dangling-name-prefix=[value]`: name image with `prefix@<digest>` , used for anonymous images
220
+* `name-canonical=true`: add additional canonical name `name@<digest>`
221
+* `compression=[uncompressed,gzip]`: choose compression type for layer, gzip is default value
222
+
223
+
212 224
 If credentials are required, `buildctl` will attempt to read Docker configuration file `$DOCKER_CONFIG/config.json`.
213 225
 `$DOCKER_CONFIG` defaults to `~/.docker`.
214 226
 
... ...
@@ -322,14 +340,11 @@ buildctl build ... \
322 322
 
323 323
 ```bash
324 324
 buildctl build ... --export-cache type=local,dest=path/to/output-dir
325
-buildctl build ... --import-cache type=local,src=path/to/input-dir,digest=sha256:deadbeef
325
+buildctl build ... --import-cache type=local,src=path/to/input-dir
326 326
 ```
327 327
 
328 328
 The directory layout conforms to OCI Image Spec v1.0.
329 329
 
330
-Currently, you need to specify the `digest` of the manifest list to import for `local` cache importer. 
331
-This is planned to default to the digest of "latest" tag in `index.json` in future.
332
-
333 330
 #### `--export-cache` options
334 331
 -   `type`: `inline`, `registry`, or `local`
335 332
 -   `mode=min` (default): only export layers for the resulting image
... ...
@@ -341,7 +356,8 @@ This is planned to default to the digest of "latest" tag in `index.json` in futu
341 341
 -   `type`: `registry` or `local`. Use `registry` to import `inline` cache.
342 342
 -   `ref=docker.io/user/image:tag`: reference for `registry` cache importer
343 343
 -   `src=path/to/input-dir`: directory for `local` cache importer
344
--   `digest=sha256:deadbeef`: digest of the manifest list to import for `local` cache importer. 
344
+-   `digest=sha256:deadbeef`: digest of the manifest list to import for `local` cache importer.
345
+    Defaults to the digest of "latest" tag in `index.json`
345 346
 
346 347
 ### Consistent hashing
347 348
 
... ...
@@ -50,7 +50,7 @@ func (m *PruneRequest) Reset()         { *m = PruneRequest{} }
50 50
 func (m *PruneRequest) String() string { return proto.CompactTextString(m) }
51 51
 func (*PruneRequest) ProtoMessage()    {}
52 52
 func (*PruneRequest) Descriptor() ([]byte, []int) {
53
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{0}
53
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{0}
54 54
 }
55 55
 func (m *PruneRequest) XXX_Unmarshal(b []byte) error {
56 56
 	return m.Unmarshal(b)
... ...
@@ -118,7 +118,7 @@ func (m *DiskUsageRequest) Reset()         { *m = DiskUsageRequest{} }
118 118
 func (m *DiskUsageRequest) String() string { return proto.CompactTextString(m) }
119 119
 func (*DiskUsageRequest) ProtoMessage()    {}
120 120
 func (*DiskUsageRequest) Descriptor() ([]byte, []int) {
121
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{1}
121
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{1}
122 122
 }
123 123
 func (m *DiskUsageRequest) XXX_Unmarshal(b []byte) error {
124 124
 	return m.Unmarshal(b)
... ...
@@ -165,7 +165,7 @@ func (m *DiskUsageResponse) Reset()         { *m = DiskUsageResponse{} }
165 165
 func (m *DiskUsageResponse) String() string { return proto.CompactTextString(m) }
166 166
 func (*DiskUsageResponse) ProtoMessage()    {}
167 167
 func (*DiskUsageResponse) Descriptor() ([]byte, []int) {
168
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{2}
168
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{2}
169 169
 }
170 170
 func (m *DiskUsageResponse) XXX_Unmarshal(b []byte) error {
171 171
 	return m.Unmarshal(b)
... ...
@@ -222,7 +222,7 @@ func (m *UsageRecord) Reset()         { *m = UsageRecord{} }
222 222
 func (m *UsageRecord) String() string { return proto.CompactTextString(m) }
223 223
 func (*UsageRecord) ProtoMessage()    {}
224 224
 func (*UsageRecord) Descriptor() ([]byte, []int) {
225
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{3}
225
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{3}
226 226
 }
227 227
 func (m *UsageRecord) XXX_Unmarshal(b []byte) error {
228 228
 	return m.Unmarshal(b)
... ...
@@ -338,6 +338,7 @@ type SolveRequest struct {
338 338
 	FrontendAttrs        map[string]string                                        `protobuf:"bytes,7,rep,name=FrontendAttrs,proto3" json:"FrontendAttrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
339 339
 	Cache                CacheOptions                                             `protobuf:"bytes,8,opt,name=Cache,proto3" json:"Cache"`
340 340
 	Entitlements         []github_com_moby_buildkit_util_entitlements.Entitlement `protobuf:"bytes,9,rep,name=Entitlements,proto3,customtype=github.com/moby/buildkit/util/entitlements.Entitlement" json:"Entitlements,omitempty"`
341
+	FrontendInputs       map[string]*pb.Definition                                `protobuf:"bytes,10,rep,name=FrontendInputs,proto3" json:"FrontendInputs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
341 342
 	XXX_NoUnkeyedLiteral struct{}                                                 `json:"-"`
342 343
 	XXX_unrecognized     []byte                                                   `json:"-"`
343 344
 	XXX_sizecache        int32                                                    `json:"-"`
... ...
@@ -347,7 +348,7 @@ func (m *SolveRequest) Reset()         { *m = SolveRequest{} }
347 347
 func (m *SolveRequest) String() string { return proto.CompactTextString(m) }
348 348
 func (*SolveRequest) ProtoMessage()    {}
349 349
 func (*SolveRequest) Descriptor() ([]byte, []int) {
350
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{4}
350
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{4}
351 351
 }
352 352
 func (m *SolveRequest) XXX_Unmarshal(b []byte) error {
353 353
 	return m.Unmarshal(b)
... ...
@@ -432,6 +433,13 @@ func (m *SolveRequest) GetCache() CacheOptions {
432 432
 	return CacheOptions{}
433 433
 }
434 434
 
435
+func (m *SolveRequest) GetFrontendInputs() map[string]*pb.Definition {
436
+	if m != nil {
437
+		return m.FrontendInputs
438
+	}
439
+	return nil
440
+}
441
+
435 442
 type CacheOptions struct {
436 443
 	// ExportRefDeprecated is deprecated in favor or the new Exports since BuildKit v0.4.0.
437 444
 	// When ExportRefDeprecated is set, the solver appends
... ...
@@ -459,7 +467,7 @@ func (m *CacheOptions) Reset()         { *m = CacheOptions{} }
459 459
 func (m *CacheOptions) String() string { return proto.CompactTextString(m) }
460 460
 func (*CacheOptions) ProtoMessage()    {}
461 461
 func (*CacheOptions) Descriptor() ([]byte, []int) {
462
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{5}
462
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{5}
463 463
 }
464 464
 func (m *CacheOptions) XXX_Unmarshal(b []byte) error {
465 465
 	return m.Unmarshal(b)
... ...
@@ -538,7 +546,7 @@ func (m *CacheOptionsEntry) Reset()         { *m = CacheOptionsEntry{} }
538 538
 func (m *CacheOptionsEntry) String() string { return proto.CompactTextString(m) }
539 539
 func (*CacheOptionsEntry) ProtoMessage()    {}
540 540
 func (*CacheOptionsEntry) Descriptor() ([]byte, []int) {
541
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{6}
541
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{6}
542 542
 }
543 543
 func (m *CacheOptionsEntry) XXX_Unmarshal(b []byte) error {
544 544
 	return m.Unmarshal(b)
... ...
@@ -592,7 +600,7 @@ func (m *SolveResponse) Reset()         { *m = SolveResponse{} }
592 592
 func (m *SolveResponse) String() string { return proto.CompactTextString(m) }
593 593
 func (*SolveResponse) ProtoMessage()    {}
594 594
 func (*SolveResponse) Descriptor() ([]byte, []int) {
595
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{7}
595
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{7}
596 596
 }
597 597
 func (m *SolveResponse) XXX_Unmarshal(b []byte) error {
598 598
 	return m.Unmarshal(b)
... ...
@@ -639,7 +647,7 @@ func (m *StatusRequest) Reset()         { *m = StatusRequest{} }
639 639
 func (m *StatusRequest) String() string { return proto.CompactTextString(m) }
640 640
 func (*StatusRequest) ProtoMessage()    {}
641 641
 func (*StatusRequest) Descriptor() ([]byte, []int) {
642
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{8}
642
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{8}
643 643
 }
644 644
 func (m *StatusRequest) XXX_Unmarshal(b []byte) error {
645 645
 	return m.Unmarshal(b)
... ...
@@ -688,7 +696,7 @@ func (m *StatusResponse) Reset()         { *m = StatusResponse{} }
688 688
 func (m *StatusResponse) String() string { return proto.CompactTextString(m) }
689 689
 func (*StatusResponse) ProtoMessage()    {}
690 690
 func (*StatusResponse) Descriptor() ([]byte, []int) {
691
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{9}
691
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{9}
692 692
 }
693 693
 func (m *StatusResponse) XXX_Unmarshal(b []byte) error {
694 694
 	return m.Unmarshal(b)
... ...
@@ -755,7 +763,7 @@ func (m *Vertex) Reset()         { *m = Vertex{} }
755 755
 func (m *Vertex) String() string { return proto.CompactTextString(m) }
756 756
 func (*Vertex) ProtoMessage()    {}
757 757
 func (*Vertex) Descriptor() ([]byte, []int) {
758
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{10}
758
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{10}
759 759
 }
760 760
 func (m *Vertex) XXX_Unmarshal(b []byte) error {
761 761
 	return m.Unmarshal(b)
... ...
@@ -838,7 +846,7 @@ func (m *VertexStatus) Reset()         { *m = VertexStatus{} }
838 838
 func (m *VertexStatus) String() string { return proto.CompactTextString(m) }
839 839
 func (*VertexStatus) ProtoMessage()    {}
840 840
 func (*VertexStatus) Descriptor() ([]byte, []int) {
841
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{11}
841
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{11}
842 842
 }
843 843
 func (m *VertexStatus) XXX_Unmarshal(b []byte) error {
844 844
 	return m.Unmarshal(b)
... ...
@@ -930,7 +938,7 @@ func (m *VertexLog) Reset()         { *m = VertexLog{} }
930 930
 func (m *VertexLog) String() string { return proto.CompactTextString(m) }
931 931
 func (*VertexLog) ProtoMessage()    {}
932 932
 func (*VertexLog) Descriptor() ([]byte, []int) {
933
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{12}
933
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{12}
934 934
 }
935 935
 func (m *VertexLog) XXX_Unmarshal(b []byte) error {
936 936
 	return m.Unmarshal(b)
... ...
@@ -991,7 +999,7 @@ func (m *BytesMessage) Reset()         { *m = BytesMessage{} }
991 991
 func (m *BytesMessage) String() string { return proto.CompactTextString(m) }
992 992
 func (*BytesMessage) ProtoMessage()    {}
993 993
 func (*BytesMessage) Descriptor() ([]byte, []int) {
994
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{13}
994
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{13}
995 995
 }
996 996
 func (m *BytesMessage) XXX_Unmarshal(b []byte) error {
997 997
 	return m.Unmarshal(b)
... ...
@@ -1038,7 +1046,7 @@ func (m *ListWorkersRequest) Reset()         { *m = ListWorkersRequest{} }
1038 1038
 func (m *ListWorkersRequest) String() string { return proto.CompactTextString(m) }
1039 1039
 func (*ListWorkersRequest) ProtoMessage()    {}
1040 1040
 func (*ListWorkersRequest) Descriptor() ([]byte, []int) {
1041
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{14}
1041
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{14}
1042 1042
 }
1043 1043
 func (m *ListWorkersRequest) XXX_Unmarshal(b []byte) error {
1044 1044
 	return m.Unmarshal(b)
... ...
@@ -1085,7 +1093,7 @@ func (m *ListWorkersResponse) Reset()         { *m = ListWorkersResponse{} }
1085 1085
 func (m *ListWorkersResponse) String() string { return proto.CompactTextString(m) }
1086 1086
 func (*ListWorkersResponse) ProtoMessage()    {}
1087 1087
 func (*ListWorkersResponse) Descriptor() ([]byte, []int) {
1088
-	return fileDescriptor_control_86d7f5d7b8f10de2, []int{15}
1088
+	return fileDescriptor_control_7e741c2ad6bf4a8a, []int{15}
1089 1089
 }
1090 1090
 func (m *ListWorkersResponse) XXX_Unmarshal(b []byte) error {
1091 1091
 	return m.Unmarshal(b)
... ...
@@ -1129,6 +1137,7 @@ func init() {
1129 1129
 	proto.RegisterType((*SolveRequest)(nil), "moby.buildkit.v1.SolveRequest")
1130 1130
 	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.SolveRequest.ExporterAttrsEntry")
1131 1131
 	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.SolveRequest.FrontendAttrsEntry")
1132
+	proto.RegisterMapType((map[string]*pb.Definition)(nil), "moby.buildkit.v1.SolveRequest.FrontendInputsEntry")
1132 1133
 	proto.RegisterType((*CacheOptions)(nil), "moby.buildkit.v1.CacheOptions")
1133 1134
 	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.CacheOptions.ExportAttrsDeprecatedEntry")
1134 1135
 	proto.RegisterType((*CacheOptionsEntry)(nil), "moby.buildkit.v1.CacheOptionsEntry")
... ...
@@ -1803,6 +1812,34 @@ func (m *SolveRequest) MarshalTo(dAtA []byte) (int, error) {
1803 1803
 			i += copy(dAtA[i:], s)
1804 1804
 		}
1805 1805
 	}
1806
+	if len(m.FrontendInputs) > 0 {
1807
+		for k, _ := range m.FrontendInputs {
1808
+			dAtA[i] = 0x52
1809
+			i++
1810
+			v := m.FrontendInputs[k]
1811
+			msgSize := 0
1812
+			if v != nil {
1813
+				msgSize = v.Size()
1814
+				msgSize += 1 + sovControl(uint64(msgSize))
1815
+			}
1816
+			mapSize := 1 + len(k) + sovControl(uint64(len(k))) + msgSize
1817
+			i = encodeVarintControl(dAtA, i, uint64(mapSize))
1818
+			dAtA[i] = 0xa
1819
+			i++
1820
+			i = encodeVarintControl(dAtA, i, uint64(len(k)))
1821
+			i += copy(dAtA[i:], k)
1822
+			if v != nil {
1823
+				dAtA[i] = 0x12
1824
+				i++
1825
+				i = encodeVarintControl(dAtA, i, uint64(v.Size()))
1826
+				n5, err := v.MarshalTo(dAtA[i:])
1827
+				if err != nil {
1828
+					return 0, err
1829
+				}
1830
+				i += n5
1831
+			}
1832
+		}
1833
+	}
1806 1834
 	if m.XXX_unrecognized != nil {
1807 1835
 		i += copy(dAtA[i:], m.XXX_unrecognized)
1808 1836
 	}
... ...
@@ -2114,21 +2151,21 @@ func (m *Vertex) MarshalTo(dAtA []byte) (int, error) {
2114 2114
 		dAtA[i] = 0x2a
2115 2115
 		i++
2116 2116
 		i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.Started)))
2117
-		n5, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Started, dAtA[i:])
2117
+		n6, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Started, dAtA[i:])
2118 2118
 		if err != nil {
2119 2119
 			return 0, err
2120 2120
 		}
2121
-		i += n5
2121
+		i += n6
2122 2122
 	}
2123 2123
 	if m.Completed != nil {
2124 2124
 		dAtA[i] = 0x32
2125 2125
 		i++
2126 2126
 		i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.Completed)))
2127
-		n6, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Completed, dAtA[i:])
2127
+		n7, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Completed, dAtA[i:])
2128 2128
 		if err != nil {
2129 2129
 			return 0, err
2130 2130
 		}
2131
-		i += n6
2131
+		i += n7
2132 2132
 	}
2133 2133
 	if len(m.Error) > 0 {
2134 2134
 		dAtA[i] = 0x3a
... ...
@@ -2188,30 +2225,30 @@ func (m *VertexStatus) MarshalTo(dAtA []byte) (int, error) {
2188 2188
 	dAtA[i] = 0x32
2189 2189
 	i++
2190 2190
 	i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp)))
2191
-	n7, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
2191
+	n8, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
2192 2192
 	if err != nil {
2193 2193
 		return 0, err
2194 2194
 	}
2195
-	i += n7
2195
+	i += n8
2196 2196
 	if m.Started != nil {
2197 2197
 		dAtA[i] = 0x3a
2198 2198
 		i++
2199 2199
 		i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.Started)))
2200
-		n8, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Started, dAtA[i:])
2200
+		n9, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Started, dAtA[i:])
2201 2201
 		if err != nil {
2202 2202
 			return 0, err
2203 2203
 		}
2204
-		i += n8
2204
+		i += n9
2205 2205
 	}
2206 2206
 	if m.Completed != nil {
2207 2207
 		dAtA[i] = 0x42
2208 2208
 		i++
2209 2209
 		i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.Completed)))
2210
-		n9, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Completed, dAtA[i:])
2210
+		n10, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Completed, dAtA[i:])
2211 2211
 		if err != nil {
2212 2212
 			return 0, err
2213 2213
 		}
2214
-		i += n9
2214
+		i += n10
2215 2215
 	}
2216 2216
 	if m.XXX_unrecognized != nil {
2217 2217
 		i += copy(dAtA[i:], m.XXX_unrecognized)
... ...
@@ -2243,11 +2280,11 @@ func (m *VertexLog) MarshalTo(dAtA []byte) (int, error) {
2243 2243
 	dAtA[i] = 0x12
2244 2244
 	i++
2245 2245
 	i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp)))
2246
-	n10, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
2246
+	n11, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
2247 2247
 	if err != nil {
2248 2248
 		return 0, err
2249 2249
 	}
2250
-	i += n10
2250
+	i += n11
2251 2251
 	if m.Stream != 0 {
2252 2252
 		dAtA[i] = 0x18
2253 2253
 		i++
... ...
@@ -2532,6 +2569,19 @@ func (m *SolveRequest) Size() (n int) {
2532 2532
 			n += 1 + l + sovControl(uint64(l))
2533 2533
 		}
2534 2534
 	}
2535
+	if len(m.FrontendInputs) > 0 {
2536
+		for k, v := range m.FrontendInputs {
2537
+			_ = k
2538
+			_ = v
2539
+			l = 0
2540
+			if v != nil {
2541
+				l = v.Size()
2542
+				l += 1 + sovControl(uint64(l))
2543
+			}
2544
+			mapEntrySize := 1 + len(k) + sovControl(uint64(len(k))) + l
2545
+			n += mapEntrySize + 1 + sovControl(uint64(mapEntrySize))
2546
+		}
2547
+	}
2535 2548
 	if m.XXX_unrecognized != nil {
2536 2549
 		n += len(m.XXX_unrecognized)
2537 2550
 	}
... ...
@@ -3942,6 +3992,129 @@ func (m *SolveRequest) Unmarshal(dAtA []byte) error {
3942 3942
 			}
3943 3943
 			m.Entitlements = append(m.Entitlements, github_com_moby_buildkit_util_entitlements.Entitlement(dAtA[iNdEx:postIndex]))
3944 3944
 			iNdEx = postIndex
3945
+		case 10:
3946
+			if wireType != 2 {
3947
+				return fmt.Errorf("proto: wrong wireType = %d for field FrontendInputs", wireType)
3948
+			}
3949
+			var msglen int
3950
+			for shift := uint(0); ; shift += 7 {
3951
+				if shift >= 64 {
3952
+					return ErrIntOverflowControl
3953
+				}
3954
+				if iNdEx >= l {
3955
+					return io.ErrUnexpectedEOF
3956
+				}
3957
+				b := dAtA[iNdEx]
3958
+				iNdEx++
3959
+				msglen |= (int(b) & 0x7F) << shift
3960
+				if b < 0x80 {
3961
+					break
3962
+				}
3963
+			}
3964
+			if msglen < 0 {
3965
+				return ErrInvalidLengthControl
3966
+			}
3967
+			postIndex := iNdEx + msglen
3968
+			if postIndex > l {
3969
+				return io.ErrUnexpectedEOF
3970
+			}
3971
+			if m.FrontendInputs == nil {
3972
+				m.FrontendInputs = make(map[string]*pb.Definition)
3973
+			}
3974
+			var mapkey string
3975
+			var mapvalue *pb.Definition
3976
+			for iNdEx < postIndex {
3977
+				entryPreIndex := iNdEx
3978
+				var wire uint64
3979
+				for shift := uint(0); ; shift += 7 {
3980
+					if shift >= 64 {
3981
+						return ErrIntOverflowControl
3982
+					}
3983
+					if iNdEx >= l {
3984
+						return io.ErrUnexpectedEOF
3985
+					}
3986
+					b := dAtA[iNdEx]
3987
+					iNdEx++
3988
+					wire |= (uint64(b) & 0x7F) << shift
3989
+					if b < 0x80 {
3990
+						break
3991
+					}
3992
+				}
3993
+				fieldNum := int32(wire >> 3)
3994
+				if fieldNum == 1 {
3995
+					var stringLenmapkey uint64
3996
+					for shift := uint(0); ; shift += 7 {
3997
+						if shift >= 64 {
3998
+							return ErrIntOverflowControl
3999
+						}
4000
+						if iNdEx >= l {
4001
+							return io.ErrUnexpectedEOF
4002
+						}
4003
+						b := dAtA[iNdEx]
4004
+						iNdEx++
4005
+						stringLenmapkey |= (uint64(b) & 0x7F) << shift
4006
+						if b < 0x80 {
4007
+							break
4008
+						}
4009
+					}
4010
+					intStringLenmapkey := int(stringLenmapkey)
4011
+					if intStringLenmapkey < 0 {
4012
+						return ErrInvalidLengthControl
4013
+					}
4014
+					postStringIndexmapkey := iNdEx + intStringLenmapkey
4015
+					if postStringIndexmapkey > l {
4016
+						return io.ErrUnexpectedEOF
4017
+					}
4018
+					mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
4019
+					iNdEx = postStringIndexmapkey
4020
+				} else if fieldNum == 2 {
4021
+					var mapmsglen int
4022
+					for shift := uint(0); ; shift += 7 {
4023
+						if shift >= 64 {
4024
+							return ErrIntOverflowControl
4025
+						}
4026
+						if iNdEx >= l {
4027
+							return io.ErrUnexpectedEOF
4028
+						}
4029
+						b := dAtA[iNdEx]
4030
+						iNdEx++
4031
+						mapmsglen |= (int(b) & 0x7F) << shift
4032
+						if b < 0x80 {
4033
+							break
4034
+						}
4035
+					}
4036
+					if mapmsglen < 0 {
4037
+						return ErrInvalidLengthControl
4038
+					}
4039
+					postmsgIndex := iNdEx + mapmsglen
4040
+					if mapmsglen < 0 {
4041
+						return ErrInvalidLengthControl
4042
+					}
4043
+					if postmsgIndex > l {
4044
+						return io.ErrUnexpectedEOF
4045
+					}
4046
+					mapvalue = &pb.Definition{}
4047
+					if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil {
4048
+						return err
4049
+					}
4050
+					iNdEx = postmsgIndex
4051
+				} else {
4052
+					iNdEx = entryPreIndex
4053
+					skippy, err := skipControl(dAtA[iNdEx:])
4054
+					if err != nil {
4055
+						return err
4056
+					}
4057
+					if skippy < 0 {
4058
+						return ErrInvalidLengthControl
4059
+					}
4060
+					if (iNdEx + skippy) > postIndex {
4061
+						return io.ErrUnexpectedEOF
4062
+					}
4063
+					iNdEx += skippy
4064
+				}
4065
+			}
4066
+			m.FrontendInputs[mapkey] = mapvalue
4067
+			iNdEx = postIndex
3945 4068
 		default:
3946 4069
 			iNdEx = preIndex
3947 4070
 			skippy, err := skipControl(dAtA[iNdEx:])
... ...
@@ -5878,93 +6051,96 @@ var (
5878 5878
 	ErrIntOverflowControl   = fmt.Errorf("proto: integer overflow")
5879 5879
 )
5880 5880
 
5881
-func init() { proto.RegisterFile("control.proto", fileDescriptor_control_86d7f5d7b8f10de2) }
5882
-
5883
-var fileDescriptor_control_86d7f5d7b8f10de2 = []byte{
5884
-	// 1359 bytes of a gzipped FileDescriptorProto
5885
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x57, 0x4b, 0x6f, 0x1b, 0xb7,
5886
-	0x16, 0xce, 0x48, 0xd6, 0xeb, 0x48, 0x0e, 0x1c, 0x26, 0x37, 0x18, 0xcc, 0xc5, 0xb5, 0x75, 0x27,
5887
-	0x2d, 0x20, 0x04, 0xc9, 0xc8, 0x71, 0x9b, 0x22, 0x35, 0xda, 0x22, 0x91, 0x95, 0x22, 0x0e, 0x62,
5888
-	0x34, 0xa0, 0x93, 0x06, 0xe8, 0xa2, 0xc0, 0x48, 0xa2, 0x95, 0x81, 0x47, 0xc3, 0x29, 0xc9, 0x71,
5889
-	0xa3, 0xfe, 0x80, 0xae, 0xfb, 0x2f, 0xba, 0xea, 0xaa, 0x8b, 0xfe, 0x82, 0x02, 0x59, 0x76, 0x9d,
5890
-	0x85, 0x5b, 0x64, 0xdf, 0xae, 0xba, 0xe9, 0xae, 0xe0, 0x63, 0x64, 0xca, 0x92, 0xfc, 0xca, 0x6a,
5891
-	0x78, 0x38, 0xe7, 0xfb, 0x78, 0x5e, 0x24, 0x0f, 0x61, 0xb9, 0x4f, 0x13, 0xc1, 0x68, 0x1c, 0xa4,
5892
-	0x8c, 0x0a, 0x8a, 0x56, 0x46, 0xb4, 0x37, 0x0e, 0x7a, 0x59, 0x14, 0x0f, 0xf6, 0x23, 0x11, 0x1c,
5893
-	0xdc, 0xf1, 0x6e, 0x0f, 0x23, 0xf1, 0x32, 0xeb, 0x05, 0x7d, 0x3a, 0x6a, 0x0f, 0xe9, 0x90, 0xb6,
5894
-	0x95, 0x62, 0x2f, 0xdb, 0x53, 0x92, 0x12, 0xd4, 0x48, 0x13, 0x78, 0x6b, 0x43, 0x4a, 0x87, 0x31,
5895
-	0x39, 0xd2, 0x12, 0xd1, 0x88, 0x70, 0x11, 0x8e, 0x52, 0xa3, 0x70, 0xcb, 0xe2, 0x93, 0x8b, 0xb5,
5896
-	0xf3, 0xc5, 0xda, 0x9c, 0xc6, 0x07, 0x84, 0xb5, 0xd3, 0x5e, 0x9b, 0xa6, 0xdc, 0x68, 0xb7, 0x17,
5897
-	0x6a, 0x87, 0x69, 0xd4, 0x16, 0xe3, 0x94, 0xf0, 0xf6, 0xb7, 0x94, 0xed, 0x13, 0xa6, 0x01, 0xfe,
5898
-	0xf7, 0x0e, 0x34, 0x9e, 0xb2, 0x2c, 0x21, 0x98, 0x7c, 0x93, 0x11, 0x2e, 0xd0, 0x75, 0x28, 0xef,
5899
-	0x45, 0xb1, 0x20, 0xcc, 0x75, 0x9a, 0xc5, 0x56, 0x0d, 0x1b, 0x09, 0xad, 0x40, 0x31, 0x8c, 0x63,
5900
-	0xb7, 0xd0, 0x74, 0x5a, 0x55, 0x2c, 0x87, 0xa8, 0x05, 0x8d, 0x7d, 0x42, 0xd2, 0x6e, 0xc6, 0x42,
5901
-	0x11, 0xd1, 0xc4, 0x2d, 0x36, 0x9d, 0x56, 0xb1, 0xb3, 0xf4, 0xfa, 0x70, 0xcd, 0xc1, 0x53, 0x7f,
5902
-	0x90, 0x0f, 0x35, 0x29, 0x77, 0xc6, 0x82, 0x70, 0x77, 0xc9, 0x52, 0x3b, 0x9a, 0xf6, 0x6f, 0xc2,
5903
-	0x4a, 0x37, 0xe2, 0xfb, 0xcf, 0x79, 0x38, 0x3c, 0xcd, 0x16, 0xff, 0x31, 0x5c, 0xb1, 0x74, 0x79,
5904
-	0x4a, 0x13, 0x4e, 0xd0, 0x5d, 0x28, 0x33, 0xd2, 0xa7, 0x6c, 0xa0, 0x94, 0xeb, 0x1b, 0xff, 0x0b,
5905
-	0x8e, 0xe7, 0x26, 0x30, 0x00, 0xa9, 0x84, 0x8d, 0xb2, 0xff, 0x4f, 0x01, 0xea, 0xd6, 0x3c, 0xba,
5906
-	0x0c, 0x85, 0xed, 0xae, 0xeb, 0x34, 0x9d, 0x56, 0x0d, 0x17, 0xb6, 0xbb, 0xc8, 0x85, 0xca, 0x4e,
5907
-	0x26, 0xc2, 0x5e, 0x4c, 0x8c, 0xef, 0xb9, 0x88, 0xae, 0x41, 0x69, 0x3b, 0x79, 0xce, 0x89, 0x72,
5908
-	0xbc, 0x8a, 0xb5, 0x80, 0x10, 0x2c, 0xed, 0x46, 0xdf, 0x11, 0xed, 0x26, 0x56, 0x63, 0xe9, 0xc7,
5909
-	0xd3, 0x90, 0x91, 0x44, 0xb8, 0x25, 0xc5, 0x6b, 0x24, 0xd4, 0x81, 0xda, 0x16, 0x23, 0xa1, 0x20,
5910
-	0x83, 0x07, 0xc2, 0x2d, 0x37, 0x9d, 0x56, 0x7d, 0xc3, 0x0b, 0x74, 0x41, 0x04, 0x79, 0x41, 0x04,
5911
-	0xcf, 0xf2, 0x82, 0xe8, 0x54, 0x5f, 0x1f, 0xae, 0x5d, 0xfa, 0xe1, 0x77, 0x19, 0xb7, 0x09, 0x0c,
5912
-	0xdd, 0x07, 0x78, 0x12, 0x72, 0xf1, 0x9c, 0x2b, 0x92, 0xca, 0xa9, 0x24, 0x4b, 0x8a, 0xc0, 0xc2,
5913
-	0xa0, 0x55, 0x00, 0x15, 0x80, 0x2d, 0x9a, 0x25, 0xc2, 0xad, 0x2a, 0xbb, 0xad, 0x19, 0xd4, 0x84,
5914
-	0x7a, 0x97, 0xf0, 0x3e, 0x8b, 0x52, 0x95, 0xe6, 0x9a, 0x72, 0xc1, 0x9e, 0x92, 0x0c, 0x3a, 0x7a,
5915
-	0xcf, 0xc6, 0x29, 0x71, 0x41, 0x29, 0x58, 0x33, 0xd2, 0xff, 0xdd, 0x97, 0x21, 0x23, 0x03, 0xb7,
5916
-	0xae, 0x42, 0x65, 0x24, 0xff, 0xef, 0x25, 0x68, 0xec, 0xca, 0x2a, 0xce, 0x13, 0xbe, 0x02, 0x45,
5917
-	0x4c, 0xf6, 0x4c, 0xf4, 0xe5, 0x10, 0x05, 0x00, 0x5d, 0xb2, 0x17, 0x25, 0x91, 0x5a, 0xbb, 0xa0,
5918
-	0xdc, 0xbb, 0x1c, 0xa4, 0xbd, 0xe0, 0x68, 0x16, 0x5b, 0x1a, 0xc8, 0x83, 0xea, 0xc3, 0x57, 0x29,
5919
-	0x65, 0xb2, 0x68, 0x8a, 0x8a, 0x66, 0x22, 0xa3, 0x17, 0xb0, 0x9c, 0x8f, 0x1f, 0x08, 0xc1, 0x64,
5920
-	0x29, 0xca, 0x42, 0xb9, 0x33, 0x5b, 0x28, 0xb6, 0x51, 0xc1, 0x14, 0xe6, 0x61, 0x22, 0xd8, 0x18,
5921
-	0x4f, 0xf3, 0xc8, 0x1a, 0xd9, 0x25, 0x9c, 0x4b, 0x0b, 0x75, 0x82, 0x73, 0x51, 0x9a, 0xf3, 0x39,
5922
-	0xa3, 0x89, 0x20, 0xc9, 0x40, 0x25, 0xb8, 0x86, 0x27, 0xb2, 0x34, 0x27, 0x1f, 0x6b, 0x73, 0x2a,
5923
-	0x67, 0x32, 0x67, 0x0a, 0x63, 0xcc, 0x99, 0x9a, 0x43, 0x9b, 0x50, 0xda, 0x0a, 0xfb, 0x2f, 0x89,
5924
-	0xca, 0x65, 0x7d, 0x63, 0x75, 0x96, 0x50, 0xfd, 0xfe, 0x42, 0x25, 0x8f, 0xab, 0xad, 0x78, 0x09,
5925
-	0x6b, 0x08, 0xfa, 0x1a, 0x1a, 0x0f, 0x13, 0x11, 0x89, 0x98, 0x8c, 0x48, 0x22, 0xb8, 0x5b, 0x93,
5926
-	0x1b, 0xaf, 0xb3, 0xf9, 0xe6, 0x70, 0xed, 0xa3, 0x85, 0x47, 0x4b, 0x26, 0xa2, 0xb8, 0x4d, 0x2c,
5927
-	0x54, 0x60, 0x51, 0xe0, 0x29, 0x3e, 0xef, 0x3e, 0xa0, 0xd9, 0x78, 0xca, 0xbc, 0xef, 0x93, 0x71,
5928
-	0x9e, 0xf7, 0x7d, 0x32, 0x96, 0x9b, 0xeb, 0x20, 0x8c, 0x33, 0xbd, 0xe9, 0x6a, 0x58, 0x0b, 0x9b,
5929
-	0x85, 0x7b, 0x8e, 0x64, 0x98, 0x0d, 0xc1, 0x79, 0x18, 0xfc, 0x9f, 0x8a, 0xd0, 0xb0, 0x23, 0x80,
5930
-	0xd6, 0xe1, 0xaa, 0x36, 0x0a, 0x93, 0xbd, 0x2e, 0x49, 0x19, 0xe9, 0xcb, 0xcd, 0x65, 0xc8, 0xe6,
5931
-	0xfd, 0x42, 0x1b, 0x70, 0x6d, 0x7b, 0x64, 0xa6, 0xb9, 0x05, 0x29, 0xa8, 0x73, 0x6a, 0xee, 0x3f,
5932
-	0x44, 0xe1, 0x3f, 0x9a, 0x4a, 0x99, 0x6d, 0x81, 0x8a, 0x2a, 0xef, 0x1f, 0x9f, 0x9c, 0xa6, 0x60,
5933
-	0x2e, 0x56, 0xe7, 0x7f, 0x3e, 0x2f, 0xfa, 0x14, 0x2a, 0xfa, 0x47, 0x5e, 0xe9, 0x37, 0x4e, 0x5e,
5934
-	0x42, 0x93, 0xe5, 0x18, 0x09, 0xd7, 0x7e, 0x70, 0xb7, 0x74, 0x0e, 0xb8, 0xc1, 0x78, 0x8f, 0xc0,
5935
-	0x5b, 0x6c, 0xf2, 0xb9, 0xf2, 0xf5, 0xa3, 0x03, 0x57, 0x66, 0x16, 0x92, 0x07, 0xad, 0x3a, 0x6e,
5936
-	0x34, 0x85, 0x1a, 0xa3, 0x2e, 0x94, 0xf4, 0x56, 0x2a, 0x28, 0x83, 0x83, 0x33, 0x18, 0x1c, 0x58,
5937
-	0xfb, 0x48, 0x83, 0xbd, 0x7b, 0x00, 0x17, 0xac, 0xac, 0x5f, 0x1c, 0x58, 0x36, 0x9b, 0xd5, 0xdc,
5938
-	0x4a, 0x21, 0xac, 0xe4, 0xf5, 0x9e, 0xcf, 0x99, 0xfb, 0xe9, 0xee, 0xc2, 0x7d, 0xae, 0xd5, 0x82,
5939
-	0xe3, 0x38, 0x6d, 0xe3, 0x0c, 0x9d, 0xb7, 0x95, 0xd7, 0xd5, 0x31, 0xd5, 0x73, 0x59, 0xfe, 0x7f,
5940
-	0x58, 0xde, 0x15, 0xa1, 0xc8, 0xf8, 0xc2, 0xa3, 0xd8, 0xff, 0xd9, 0x81, 0xcb, 0xb9, 0x8e, 0xf1,
5941
-	0xee, 0x43, 0xa8, 0x1e, 0x10, 0x26, 0xc8, 0x2b, 0xc2, 0x8d, 0x57, 0xee, 0xac, 0x57, 0x5f, 0x2a,
5942
-	0x0d, 0x3c, 0xd1, 0x44, 0x9b, 0x50, 0xe5, 0x8a, 0x87, 0xe4, 0x89, 0x5a, 0x5d, 0x84, 0x32, 0xeb,
5943
-	0x4d, 0xf4, 0x51, 0x1b, 0x96, 0x62, 0x3a, 0xe4, 0x66, 0xcf, 0xfc, 0x77, 0x11, 0xee, 0x09, 0x1d,
5944
-	0x62, 0xa5, 0xe8, 0x1f, 0x16, 0xa0, 0xac, 0xe7, 0xd0, 0x63, 0x28, 0x0f, 0xa2, 0x21, 0xe1, 0x42,
5945
-	0x7b, 0xd5, 0xd9, 0x90, 0x07, 0xdf, 0x9b, 0xc3, 0xb5, 0x9b, 0xd6, 0xc9, 0x46, 0x53, 0x92, 0xc8,
5946
-	0x16, 0x2f, 0x8c, 0x12, 0xc2, 0x78, 0x7b, 0x48, 0x6f, 0x6b, 0x48, 0xd0, 0x55, 0x1f, 0x6c, 0x18,
5947
-	0x24, 0x57, 0x94, 0xa4, 0x99, 0xd0, 0x1e, 0x5c, 0x90, 0x4b, 0x33, 0xc8, 0x4a, 0x4e, 0xc2, 0x11,
5948
-	0x31, 0xf7, 0x95, 0x1a, 0xcb, 0x2b, 0xb3, 0x2f, 0x4b, 0x75, 0xa0, 0x1a, 0x89, 0x2a, 0x36, 0x12,
5949
-	0xda, 0x84, 0x0a, 0x17, 0x21, 0x93, 0xc7, 0x46, 0xe9, 0x8c, 0x77, 0x7d, 0x0e, 0x40, 0x9f, 0x41,
5950
-	0xad, 0x4f, 0x47, 0x69, 0x4c, 0x24, 0xba, 0x7c, 0x46, 0xf4, 0x11, 0x44, 0x56, 0x0f, 0x61, 0x8c,
5951
-	0x32, 0xd5, 0x65, 0xd4, 0xb0, 0x16, 0xfc, 0xbf, 0x0a, 0xd0, 0xb0, 0x93, 0x35, 0xd3, 0x41, 0x3d,
5952
-	0x86, 0xb2, 0x4e, 0xbd, 0xae, 0xba, 0x8b, 0x85, 0x4a, 0x33, 0xcc, 0x0d, 0x95, 0x0b, 0x95, 0x7e,
5953
-	0xc6, 0x54, 0x7b, 0xa5, 0x9b, 0xae, 0x5c, 0x94, 0x06, 0x0b, 0x2a, 0xc2, 0x58, 0x85, 0xaa, 0x88,
5954
-	0xb5, 0x20, 0xbb, 0xae, 0x49, 0x93, 0x7d, 0xbe, 0xae, 0x6b, 0x02, 0xb3, 0xd3, 0x50, 0x79, 0xa7,
5955
-	0x34, 0x54, 0xcf, 0x9d, 0x06, 0xff, 0x57, 0x07, 0x6a, 0x93, 0x2a, 0xb7, 0xa2, 0xeb, 0xbc, 0x73,
5956
-	0x74, 0xa7, 0x22, 0x53, 0xb8, 0x58, 0x64, 0xae, 0x43, 0x99, 0x0b, 0x46, 0xc2, 0x91, 0x7e, 0x0f,
5957
-	0x60, 0x23, 0xc9, 0xf3, 0x64, 0xc4, 0x87, 0x2a, 0x43, 0x0d, 0x2c, 0x87, 0xbe, 0x0f, 0x0d, 0xd5,
5958
-	0xfa, 0xef, 0x10, 0x2e, 0x9b, 0x4d, 0x99, 0xdb, 0x41, 0x28, 0x42, 0xe5, 0x47, 0x03, 0xab, 0xb1,
5959
-	0x7f, 0x0b, 0xd0, 0x93, 0x88, 0x8b, 0x17, 0xea, 0xc9, 0xc2, 0x4f, 0x7b, 0x17, 0xec, 0xc2, 0xd5,
5960
-	0x29, 0x6d, 0x73, 0x4a, 0x7d, 0x72, 0xec, 0x65, 0xf0, 0xde, 0xec, 0xa9, 0xa1, 0x5e, 0x46, 0x81,
5961
-	0x06, 0x4e, 0x3f, 0x10, 0x36, 0xfe, 0x2c, 0x42, 0x65, 0x4b, 0x3f, 0xfa, 0xd0, 0x33, 0xa8, 0x4d,
5962
-	0x1e, 0x1e, 0xc8, 0x9f, 0xa5, 0x39, 0xfe, 0x82, 0xf1, 0x6e, 0x9c, 0xa8, 0x63, 0xec, 0x7b, 0x04,
5963
-	0x25, 0xf5, 0x04, 0x43, 0x73, 0x8e, 0x41, 0xfb, 0x6d, 0xe6, 0x9d, 0xfc, 0xa4, 0x59, 0x77, 0x24,
5964
-	0x93, 0xba, 0x43, 0xe6, 0x31, 0xd9, 0x4d, 0xa4, 0xb7, 0x76, 0xca, 0xe5, 0x83, 0x76, 0xa0, 0x6c,
5965
-	0xb6, 0xf3, 0x3c, 0x55, 0xfb, 0xa6, 0xf0, 0x9a, 0x8b, 0x15, 0x34, 0xd9, 0xba, 0x83, 0x76, 0x26,
5966
-	0x1d, 0xf2, 0x3c, 0xd3, 0xec, 0x32, 0xf0, 0x4e, 0xf9, 0xdf, 0x72, 0xd6, 0x1d, 0xf4, 0x15, 0xd4,
5967
-	0xad, 0x44, 0xa3, 0x39, 0x09, 0x9d, 0xad, 0x1a, 0xef, 0xfd, 0x53, 0xb4, 0xb4, 0xb1, 0x9d, 0xc6,
5968
-	0xeb, 0xb7, 0xab, 0xce, 0x6f, 0x6f, 0x57, 0x9d, 0x3f, 0xde, 0xae, 0x3a, 0xbd, 0xb2, 0xaa, 0xfb,
5969
-	0x0f, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xd3, 0x7a, 0xbe, 0x54, 0xf8, 0x0f, 0x00, 0x00,
5881
+func init() { proto.RegisterFile("control.proto", fileDescriptor_control_7e741c2ad6bf4a8a) }
5882
+
5883
+var fileDescriptor_control_7e741c2ad6bf4a8a = []byte{
5884
+	// 1397 bytes of a gzipped FileDescriptorProto
5885
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x57, 0x4d, 0x6f, 0x1b, 0xc5,
5886
+	0x1b, 0xef, 0xda, 0xf1, 0xdb, 0x63, 0x27, 0x4a, 0xa7, 0xfd, 0x57, 0xab, 0xfd, 0x8b, 0xc4, 0x6c,
5887
+	0x8b, 0x64, 0x55, 0xed, 0x3a, 0x35, 0x14, 0x95, 0x08, 0x50, 0xeb, 0xb8, 0xa8, 0xa9, 0x1a, 0x51,
5888
+	0x36, 0x2d, 0x95, 0x7a, 0x40, 0x5a, 0xdb, 0x13, 0x77, 0x95, 0xf5, 0xce, 0x32, 0x33, 0x1b, 0x6a,
5889
+	0x3e, 0x00, 0x67, 0xbe, 0x03, 0x07, 0x4e, 0x9c, 0x38, 0xf0, 0x09, 0x90, 0x7a, 0xe4, 0xdc, 0x43,
5890
+	0x40, 0xb9, 0xc3, 0x9d, 0x1b, 0x9a, 0x97, 0x75, 0xc6, 0xb1, 0x9d, 0xc4, 0xe9, 0xc9, 0xf3, 0x8c,
5891
+	0x9f, 0xdf, 0x6f, 0x9f, 0xd7, 0x99, 0x79, 0x60, 0xb9, 0x47, 0x62, 0x4e, 0x49, 0xe4, 0x25, 0x94,
5892
+	0x70, 0x82, 0x56, 0x87, 0xa4, 0x3b, 0xf2, 0xba, 0x69, 0x18, 0xf5, 0xf7, 0x43, 0xee, 0x1d, 0xdc,
5893
+	0x71, 0x6e, 0x0f, 0x42, 0xfe, 0x2a, 0xed, 0x7a, 0x3d, 0x32, 0x6c, 0x0e, 0xc8, 0x80, 0x34, 0xa5,
5894
+	0x62, 0x37, 0xdd, 0x93, 0x92, 0x14, 0xe4, 0x4a, 0x11, 0x38, 0xeb, 0x03, 0x42, 0x06, 0x11, 0x3e,
5895
+	0xd6, 0xe2, 0xe1, 0x10, 0x33, 0x1e, 0x0c, 0x13, 0xad, 0x70, 0xcb, 0xe0, 0x13, 0x1f, 0x6b, 0x66,
5896
+	0x1f, 0x6b, 0x32, 0x12, 0x1d, 0x60, 0xda, 0x4c, 0xba, 0x4d, 0x92, 0x30, 0xad, 0xdd, 0x9c, 0xab,
5897
+	0x1d, 0x24, 0x61, 0x93, 0x8f, 0x12, 0xcc, 0x9a, 0xdf, 0x11, 0xba, 0x8f, 0xa9, 0x02, 0xb8, 0x3f,
5898
+	0x58, 0x50, 0x7b, 0x4a, 0xd3, 0x18, 0xfb, 0xf8, 0xdb, 0x14, 0x33, 0x8e, 0xae, 0x41, 0x71, 0x2f,
5899
+	0x8c, 0x38, 0xa6, 0xb6, 0x55, 0xcf, 0x37, 0x2a, 0xbe, 0x96, 0xd0, 0x2a, 0xe4, 0x83, 0x28, 0xb2,
5900
+	0x73, 0x75, 0xab, 0x51, 0xf6, 0xc5, 0x12, 0x35, 0xa0, 0xb6, 0x8f, 0x71, 0xd2, 0x49, 0x69, 0xc0,
5901
+	0x43, 0x12, 0xdb, 0xf9, 0xba, 0xd5, 0xc8, 0xb7, 0x97, 0xde, 0x1c, 0xae, 0x5b, 0xfe, 0xc4, 0x3f,
5902
+	0xc8, 0x85, 0x8a, 0x90, 0xdb, 0x23, 0x8e, 0x99, 0xbd, 0x64, 0xa8, 0x1d, 0x6f, 0xbb, 0x37, 0x61,
5903
+	0xb5, 0x13, 0xb2, 0xfd, 0xe7, 0x2c, 0x18, 0x9c, 0x65, 0x8b, 0xfb, 0x18, 0x2e, 0x1b, 0xba, 0x2c,
5904
+	0x21, 0x31, 0xc3, 0xe8, 0x2e, 0x14, 0x29, 0xee, 0x11, 0xda, 0x97, 0xca, 0xd5, 0xd6, 0x7b, 0xde,
5905
+	0xc9, 0xdc, 0x78, 0x1a, 0x20, 0x94, 0x7c, 0xad, 0xec, 0xfe, 0x9b, 0x83, 0xaa, 0xb1, 0x8f, 0x56,
5906
+	0x20, 0xb7, 0xdd, 0xb1, 0xad, 0xba, 0xd5, 0xa8, 0xf8, 0xb9, 0xed, 0x0e, 0xb2, 0xa1, 0xb4, 0x93,
5907
+	0xf2, 0xa0, 0x1b, 0x61, 0xed, 0x7b, 0x26, 0xa2, 0xab, 0x50, 0xd8, 0x8e, 0x9f, 0x33, 0x2c, 0x1d,
5908
+	0x2f, 0xfb, 0x4a, 0x40, 0x08, 0x96, 0x76, 0xc3, 0xef, 0xb1, 0x72, 0xd3, 0x97, 0x6b, 0xe1, 0xc7,
5909
+	0xd3, 0x80, 0xe2, 0x98, 0xdb, 0x05, 0xc9, 0xab, 0x25, 0xd4, 0x86, 0xca, 0x16, 0xc5, 0x01, 0xc7,
5910
+	0xfd, 0x07, 0xdc, 0x2e, 0xd6, 0xad, 0x46, 0xb5, 0xe5, 0x78, 0xaa, 0x20, 0xbc, 0xac, 0x20, 0xbc,
5911
+	0x67, 0x59, 0x41, 0xb4, 0xcb, 0x6f, 0x0e, 0xd7, 0x2f, 0xfd, 0xf8, 0xa7, 0x88, 0xdb, 0x18, 0x86,
5912
+	0xee, 0x03, 0x3c, 0x09, 0x18, 0x7f, 0xce, 0x24, 0x49, 0xe9, 0x4c, 0x92, 0x25, 0x49, 0x60, 0x60,
5913
+	0xd0, 0x1a, 0x80, 0x0c, 0xc0, 0x16, 0x49, 0x63, 0x6e, 0x97, 0xa5, 0xdd, 0xc6, 0x0e, 0xaa, 0x43,
5914
+	0xb5, 0x83, 0x59, 0x8f, 0x86, 0x89, 0x4c, 0x73, 0x45, 0xba, 0x60, 0x6e, 0x09, 0x06, 0x15, 0xbd,
5915
+	0x67, 0xa3, 0x04, 0xdb, 0x20, 0x15, 0x8c, 0x1d, 0xe1, 0xff, 0xee, 0xab, 0x80, 0xe2, 0xbe, 0x5d,
5916
+	0x95, 0xa1, 0xd2, 0x92, 0xfb, 0x53, 0x11, 0x6a, 0xbb, 0xa2, 0x8a, 0xb3, 0x84, 0xaf, 0x42, 0xde,
5917
+	0xc7, 0x7b, 0x3a, 0xfa, 0x62, 0x89, 0x3c, 0x80, 0x0e, 0xde, 0x0b, 0xe3, 0x50, 0x7e, 0x3b, 0x27,
5918
+	0xdd, 0x5b, 0xf1, 0x92, 0xae, 0x77, 0xbc, 0xeb, 0x1b, 0x1a, 0xc8, 0x81, 0xf2, 0xc3, 0xd7, 0x09,
5919
+	0xa1, 0xa2, 0x68, 0xf2, 0x92, 0x66, 0x2c, 0xa3, 0x17, 0xb0, 0x9c, 0xad, 0x1f, 0x70, 0x4e, 0x45,
5920
+	0x29, 0x8a, 0x42, 0xb9, 0x33, 0x5d, 0x28, 0xa6, 0x51, 0xde, 0x04, 0xe6, 0x61, 0xcc, 0xe9, 0xc8,
5921
+	0x9f, 0xe4, 0x11, 0x35, 0xb2, 0x8b, 0x19, 0x13, 0x16, 0xaa, 0x04, 0x67, 0xa2, 0x30, 0xe7, 0x0b,
5922
+	0x4a, 0x62, 0x8e, 0xe3, 0xbe, 0x4c, 0x70, 0xc5, 0x1f, 0xcb, 0xc2, 0x9c, 0x6c, 0xad, 0xcc, 0x29,
5923
+	0x9d, 0xcb, 0x9c, 0x09, 0x8c, 0x36, 0x67, 0x62, 0x0f, 0x6d, 0x42, 0x61, 0x2b, 0xe8, 0xbd, 0xc2,
5924
+	0x32, 0x97, 0xd5, 0xd6, 0xda, 0x34, 0xa1, 0xfc, 0xfb, 0x4b, 0x99, 0x3c, 0x26, 0x5b, 0xf1, 0x92,
5925
+	0xaf, 0x20, 0xe8, 0x1b, 0xa8, 0x3d, 0x8c, 0x79, 0xc8, 0x23, 0x3c, 0xc4, 0x31, 0x67, 0x76, 0x45,
5926
+	0x34, 0x5e, 0x7b, 0xf3, 0xed, 0xe1, 0xfa, 0xc7, 0x73, 0x8f, 0x96, 0x94, 0x87, 0x51, 0x13, 0x1b,
5927
+	0x28, 0xcf, 0xa0, 0xf0, 0x27, 0xf8, 0xd0, 0x4b, 0x58, 0xc9, 0x8c, 0xdd, 0x8e, 0x93, 0x94, 0x33,
5928
+	0x1b, 0xa4, 0xd7, 0xad, 0x73, 0x7a, 0xad, 0x40, 0xca, 0xed, 0x13, 0x4c, 0xce, 0x7d, 0x40, 0xd3,
5929
+	0xb9, 0x12, 0x35, 0xb5, 0x8f, 0x47, 0x59, 0x4d, 0xed, 0xe3, 0x91, 0x68, 0xdc, 0x83, 0x20, 0x4a,
5930
+	0x55, 0x43, 0x57, 0x7c, 0x25, 0x6c, 0xe6, 0xee, 0x59, 0x82, 0x61, 0x3a, 0xbc, 0x0b, 0x31, 0x7c,
5931
+	0x05, 0x57, 0x66, 0x98, 0x3a, 0x83, 0xe2, 0x86, 0x49, 0x31, 0x5d, 0xd3, 0xc7, 0x94, 0xee, 0x2f,
5932
+	0x79, 0xa8, 0x99, 0x09, 0x43, 0x1b, 0x70, 0x45, 0xf9, 0xe9, 0xe3, 0xbd, 0x0e, 0x4e, 0x28, 0xee,
5933
+	0x89, 0xb3, 0x40, 0x93, 0xcf, 0xfa, 0x0b, 0xb5, 0xe0, 0xea, 0xf6, 0x50, 0x6f, 0x33, 0x03, 0x92,
5934
+	0x93, 0xc7, 0xea, 0xcc, 0xff, 0x10, 0x81, 0xff, 0x29, 0x2a, 0x19, 0x09, 0x03, 0x94, 0x97, 0x09,
5935
+	0xfb, 0xe4, 0xf4, 0xaa, 0xf2, 0x66, 0x62, 0x55, 0xde, 0x66, 0xf3, 0xa2, 0xcf, 0xa0, 0xa4, 0xfe,
5936
+	0xc8, 0x1a, 0xf3, 0xfa, 0xe9, 0x9f, 0x50, 0x64, 0x19, 0x46, 0xc0, 0x95, 0x1f, 0xcc, 0x2e, 0x2c,
5937
+	0x00, 0xd7, 0x18, 0xe7, 0x11, 0x38, 0xf3, 0x4d, 0x5e, 0xa4, 0x04, 0xdc, 0x9f, 0x2d, 0xb8, 0x3c,
5938
+	0xf5, 0x21, 0x71, 0x2f, 0xc8, 0xd3, 0x51, 0x51, 0xc8, 0x35, 0xea, 0x40, 0x41, 0x75, 0x7e, 0x4e,
5939
+	0x1a, 0xec, 0x9d, 0xc3, 0x60, 0xcf, 0x68, 0x7b, 0x05, 0x76, 0xee, 0x01, 0x5c, 0xac, 0x58, 0xdd,
5940
+	0xdf, 0x2c, 0x58, 0xd6, 0x5d, 0xa6, 0x2f, 0xd1, 0x00, 0x56, 0xb3, 0x16, 0xca, 0xf6, 0xf4, 0x75,
5941
+	0x7a, 0x77, 0x6e, 0x83, 0x2a, 0x35, 0xef, 0x24, 0x4e, 0xd9, 0x38, 0x45, 0xe7, 0x6c, 0x65, 0x75,
5942
+	0x75, 0x42, 0x75, 0x21, 0xcb, 0xdf, 0x87, 0xe5, 0x5d, 0x1e, 0xf0, 0x94, 0xcd, 0xbd, 0x39, 0xdc,
5943
+	0x5f, 0x2d, 0x58, 0xc9, 0x74, 0xb4, 0x77, 0x1f, 0x41, 0xf9, 0x00, 0x53, 0x8e, 0x5f, 0x63, 0xa6,
5944
+	0xbd, 0xb2, 0xa7, 0xbd, 0xfa, 0x5a, 0x6a, 0xf8, 0x63, 0x4d, 0xb4, 0x09, 0x65, 0x26, 0x79, 0x70,
5945
+	0x96, 0xa8, 0xb5, 0x79, 0x28, 0xfd, 0xbd, 0xb1, 0x3e, 0x6a, 0xc2, 0x52, 0x44, 0x06, 0x4c, 0xf7,
5946
+	0xcc, 0xff, 0xe7, 0xe1, 0x9e, 0x90, 0x81, 0x2f, 0x15, 0xdd, 0xc3, 0x1c, 0x14, 0xd5, 0x1e, 0x7a,
5947
+	0x0c, 0xc5, 0x7e, 0x38, 0xc0, 0x8c, 0x2b, 0xaf, 0xda, 0x2d, 0x71, 0x4e, 0xbf, 0x3d, 0x5c, 0xbf,
5948
+	0x69, 0x1c, 0xc4, 0x24, 0xc1, 0xb1, 0x78, 0x91, 0x06, 0x61, 0x8c, 0x29, 0x6b, 0x0e, 0xc8, 0x6d,
5949
+	0x05, 0xf1, 0x3a, 0xf2, 0xc7, 0xd7, 0x0c, 0x82, 0x2b, 0x54, 0xc7, 0xad, 0x6c, 0xf9, 0x8b, 0x71,
5950
+	0x29, 0x06, 0x51, 0xc9, 0x71, 0x30, 0xc4, 0xfa, 0x7a, 0x95, 0x6b, 0x71, 0xc3, 0xf7, 0x44, 0xa9,
5951
+	0xf6, 0xe5, 0xbb, 0xa7, 0xec, 0x6b, 0x09, 0x6d, 0x42, 0x89, 0xf1, 0x80, 0x8a, 0x63, 0xa3, 0x70,
5952
+	0xce, 0xa7, 0x49, 0x06, 0x40, 0x9f, 0x43, 0xa5, 0x47, 0x86, 0x49, 0x84, 0x05, 0xba, 0x78, 0x4e,
5953
+	0xf4, 0x31, 0x44, 0x54, 0x0f, 0xa6, 0x94, 0x50, 0xf9, 0x28, 0xaa, 0xf8, 0x4a, 0x70, 0xff, 0xc9,
5954
+	0x41, 0xcd, 0x4c, 0xd6, 0xd4, 0x83, 0xef, 0x31, 0x14, 0x55, 0xea, 0x55, 0xd5, 0x5d, 0x2c, 0x54,
5955
+	0x8a, 0x61, 0x66, 0xa8, 0x6c, 0x28, 0xf5, 0x52, 0x2a, 0x5f, 0x83, 0xea, 0x8d, 0x98, 0x89, 0xc2,
5956
+	0x60, 0x4e, 0x78, 0x10, 0xc9, 0x50, 0xe5, 0x7d, 0x25, 0x88, 0x47, 0xe2, 0x78, 0x26, 0x58, 0xec,
5957
+	0x91, 0x38, 0x86, 0x99, 0x69, 0x28, 0xbd, 0x53, 0x1a, 0xca, 0x0b, 0xa7, 0xc1, 0xfd, 0xdd, 0x82,
5958
+	0xca, 0xb8, 0xca, 0x8d, 0xe8, 0x5a, 0xef, 0x1c, 0xdd, 0x89, 0xc8, 0xe4, 0x2e, 0x16, 0x99, 0x6b,
5959
+	0x50, 0x64, 0x9c, 0xe2, 0x60, 0xa8, 0xc6, 0x17, 0x5f, 0x4b, 0xe2, 0x3c, 0x19, 0xb2, 0x81, 0xcc,
5960
+	0x50, 0xcd, 0x17, 0x4b, 0xd7, 0x85, 0x9a, 0x9c, 0x54, 0x76, 0x30, 0x13, 0x6f, 0x63, 0x91, 0xdb,
5961
+	0x7e, 0xc0, 0x03, 0xe9, 0x47, 0xcd, 0x97, 0x6b, 0xf7, 0x16, 0xa0, 0x27, 0x21, 0xe3, 0x2f, 0xe4,
5962
+	0x84, 0xc5, 0xce, 0x1a, 0x63, 0x76, 0xe1, 0xca, 0x84, 0xb6, 0x3e, 0xa5, 0x3e, 0x3d, 0x31, 0xc8,
5963
+	0xdc, 0x98, 0x3e, 0x35, 0xe4, 0x20, 0xe7, 0x29, 0xe0, 0xe4, 0x3c, 0xd3, 0xfa, 0x3b, 0x0f, 0xa5,
5964
+	0x2d, 0x35, 0xa3, 0xa2, 0x67, 0x50, 0x19, 0xcf, 0x49, 0xc8, 0x9d, 0xa6, 0x39, 0x39, 0x70, 0x39,
5965
+	0xd7, 0x4f, 0xd5, 0xd1, 0xf6, 0x3d, 0x82, 0x82, 0x9c, 0x18, 0xd1, 0x8c, 0x63, 0xd0, 0x1c, 0x25,
5966
+	0x9d, 0xd3, 0x27, 0xb0, 0x0d, 0x4b, 0x30, 0xc9, 0x3b, 0x64, 0x16, 0x93, 0xf9, 0xfa, 0x73, 0xd6,
5967
+	0xcf, 0xb8, 0x7c, 0xd0, 0x0e, 0x14, 0x75, 0x3b, 0xcf, 0x52, 0x35, 0x6f, 0x0a, 0xa7, 0x3e, 0x5f,
5968
+	0x41, 0x91, 0x6d, 0x58, 0x68, 0x67, 0xfc, 0xa0, 0x9f, 0x65, 0x9a, 0x59, 0x06, 0xce, 0x19, 0xff,
5969
+	0x37, 0xac, 0x0d, 0x0b, 0xbd, 0x84, 0xaa, 0x91, 0x68, 0x34, 0x23, 0xa1, 0xd3, 0x55, 0xe3, 0x7c,
5970
+	0x70, 0x86, 0x96, 0x32, 0xb6, 0x5d, 0x7b, 0x73, 0xb4, 0x66, 0xfd, 0x71, 0xb4, 0x66, 0xfd, 0x75,
5971
+	0xb4, 0x66, 0x75, 0x8b, 0xb2, 0xee, 0x3f, 0xfc, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x65, 0x7c,
5972
+	0xd6, 0xa7, 0x10, 0x00, 0x00,
5970 5973
 }
... ...
@@ -63,6 +63,7 @@ message SolveRequest {
63 63
 	map<string, string> FrontendAttrs = 7;
64 64
 	CacheOptions Cache = 8 [(gogoproto.nullable) = false];
65 65
 	repeated string Entitlements = 9 [(gogoproto.customtype) = "github.com/moby/buildkit/util/entitlements.Entitlement" ];
66
+	map<string, pb.Definition> FrontendInputs = 10;
66 67
 }
67 68
 
68 69
 message CacheOptions {
... ...
@@ -111,7 +111,7 @@ func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor,
111 111
 	if parent != nil {
112 112
 		pInfo := parent.Info()
113 113
 		if pInfo.ChainID == "" || pInfo.BlobChainID == "" {
114
-			return nil, errors.Errorf("failed to get ref by blob on non-adressable parent")
114
+			return nil, errors.Errorf("failed to get ref by blob on non-addressable parent")
115 115
 		}
116 116
 		chainID = imagespecidentity.ChainID([]digest.Digest{pInfo.ChainID, chainID})
117 117
 		blobChainID = imagespecidentity.ChainID([]digest.Digest{pInfo.BlobChainID, blobChainID})
... ...
@@ -254,7 +254,10 @@ func (cr *cacheRecord) Mount(ctx context.Context, readonly bool) (snapshot.Mount
254 254
 func (cr *cacheRecord) remove(ctx context.Context, removeSnapshot bool) error {
255 255
 	delete(cr.cm.records, cr.ID())
256 256
 	if cr.parent != nil {
257
-		if err := cr.parent.release(ctx); err != nil {
257
+		cr.parent.mu.Lock()
258
+		err := cr.parent.release(ctx)
259
+		cr.parent.mu.Unlock()
260
+		if err != nil {
258 261
 			return err
259 262
 		}
260 263
 	}
... ...
@@ -103,3 +103,8 @@ func (g *gatewayClientForBuild) Return(ctx context.Context, in *gatewayapi.Retur
103 103
 	ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
104 104
 	return g.gateway.Return(ctx, in, opts...)
105 105
 }
106
+
107
+func (g *gatewayClientForBuild) Inputs(ctx context.Context, in *gatewayapi.InputsRequest, opts ...grpc.CallOption) (*gatewayapi.InputsResponse, error) {
108
+	ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
109
+	return g.gateway.Inputs(ctx, in, opts...)
110
+}
106 111
new file mode 100644
... ...
@@ -0,0 +1,161 @@
0
+package llb
1
+
2
+import (
3
+	"github.com/moby/buildkit/solver/pb"
4
+	digest "github.com/opencontainers/go-digest"
5
+	specs "github.com/opencontainers/image-spec/specs-go/v1"
6
+	"github.com/pkg/errors"
7
+)
8
+
9
+// DefinitionOp implements llb.Vertex using a marshalled definition.
10
+//
11
+// For example, after marshalling a LLB state and sending over the wire, the
12
+// LLB state can be reconstructed from the definition.
13
+type DefinitionOp struct {
14
+	MarshalCache
15
+	ops       map[digest.Digest]*pb.Op
16
+	defs      map[digest.Digest][]byte
17
+	metas     map[digest.Digest]pb.OpMetadata
18
+	platforms map[digest.Digest]*specs.Platform
19
+	dgst      digest.Digest
20
+	index     pb.OutputIndex
21
+}
22
+
23
+// NewDefinitionOp returns a new operation from a marshalled definition.
24
+func NewDefinitionOp(def *pb.Definition) (*DefinitionOp, error) {
25
+	ops := make(map[digest.Digest]*pb.Op)
26
+	defs := make(map[digest.Digest][]byte)
27
+
28
+	var dgst digest.Digest
29
+	for _, dt := range def.Def {
30
+		var op pb.Op
31
+		if err := (&op).Unmarshal(dt); err != nil {
32
+			return nil, errors.Wrap(err, "failed to parse llb proto op")
33
+		}
34
+		dgst = digest.FromBytes(dt)
35
+		ops[dgst] = &op
36
+		defs[dgst] = dt
37
+	}
38
+
39
+	var index pb.OutputIndex
40
+	if dgst != "" {
41
+		index = ops[dgst].Inputs[0].Index
42
+		dgst = ops[dgst].Inputs[0].Digest
43
+	}
44
+
45
+	return &DefinitionOp{
46
+		ops:       ops,
47
+		defs:      defs,
48
+		metas:     def.Metadata,
49
+		platforms: make(map[digest.Digest]*specs.Platform),
50
+		dgst:      dgst,
51
+		index:     index,
52
+	}, nil
53
+}
54
+
55
+func (d *DefinitionOp) ToInput(c *Constraints) (*pb.Input, error) {
56
+	return d.Output().ToInput(c)
57
+}
58
+
59
+func (d *DefinitionOp) Vertex() Vertex {
60
+	return d
61
+}
62
+
63
+func (d *DefinitionOp) Validate() error {
64
+	// Scratch state has no digest, ops or metas.
65
+	if d.dgst == "" {
66
+		return nil
67
+	}
68
+
69
+	if len(d.ops) == 0 || len(d.defs) == 0 || len(d.metas) == 0 {
70
+		return errors.Errorf("invalid definition op with no ops %d %d", len(d.ops), len(d.metas))
71
+	}
72
+
73
+	_, ok := d.ops[d.dgst]
74
+	if !ok {
75
+		return errors.Errorf("invalid definition op with unknown op %q", d.dgst)
76
+	}
77
+
78
+	_, ok = d.defs[d.dgst]
79
+	if !ok {
80
+		return errors.Errorf("invalid definition op with unknown def %q", d.dgst)
81
+	}
82
+
83
+	_, ok = d.metas[d.dgst]
84
+	if !ok {
85
+		return errors.Errorf("invalid definition op with unknown metas %q", d.dgst)
86
+	}
87
+
88
+	// It is possible for d.index >= len(d.ops[d.dgst]) when depending on scratch
89
+	// images.
90
+	if d.index < 0 {
91
+		return errors.Errorf("invalid definition op with invalid index")
92
+	}
93
+
94
+	return nil
95
+}
96
+
97
+func (d *DefinitionOp) Marshal(c *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
98
+	if d.dgst == "" {
99
+		return "", nil, nil, errors.Errorf("cannot marshal empty definition op")
100
+	}
101
+
102
+	if err := d.Validate(); err != nil {
103
+		return "", nil, nil, err
104
+	}
105
+
106
+	meta := d.metas[d.dgst]
107
+	return d.dgst, d.defs[d.dgst], &meta, nil
108
+
109
+}
110
+
111
+func (d *DefinitionOp) Output() Output {
112
+	if d.dgst == "" {
113
+		return nil
114
+	}
115
+
116
+	return &output{vertex: d, platform: d.platform(), getIndex: func() (pb.OutputIndex, error) {
117
+		return d.index, nil
118
+	}}
119
+}
120
+
121
+func (d *DefinitionOp) Inputs() []Output {
122
+	if d.dgst == "" {
123
+		return nil
124
+	}
125
+
126
+	var inputs []Output
127
+
128
+	op := d.ops[d.dgst]
129
+	for _, input := range op.Inputs {
130
+		vtx := &DefinitionOp{
131
+			ops:       d.ops,
132
+			defs:      d.defs,
133
+			metas:     d.metas,
134
+			platforms: d.platforms,
135
+			dgst:      input.Digest,
136
+			index:     input.Index,
137
+		}
138
+		inputs = append(inputs, &output{vertex: vtx, platform: d.platform(), getIndex: func() (pb.OutputIndex, error) {
139
+			return pb.OutputIndex(vtx.index), nil
140
+		}})
141
+	}
142
+
143
+	return inputs
144
+}
145
+
146
+func (d *DefinitionOp) platform() *specs.Platform {
147
+	platform, ok := d.platforms[d.dgst]
148
+	if ok {
149
+		return platform
150
+	}
151
+
152
+	op := d.ops[d.dgst]
153
+	if op.Platform != nil {
154
+		spec := op.Platform.Spec()
155
+		platform = &spec
156
+	}
157
+
158
+	d.platforms[d.dgst] = platform
159
+	return platform
160
+}
... ...
@@ -10,7 +10,6 @@ import (
10 10
 	"github.com/containerd/containerd/remotes/docker"
11 11
 	"github.com/docker/docker/pkg/locker"
12 12
 	"github.com/moby/buildkit/client/llb"
13
-	gw "github.com/moby/buildkit/frontend/gateway/client"
14 13
 	"github.com/moby/buildkit/util/contentutil"
15 14
 	"github.com/moby/buildkit/util/imageutil"
16 15
 	digest "github.com/opencontainers/go-digest"
... ...
@@ -72,7 +71,7 @@ type resolveResult struct {
72 72
 	dgst   digest.Digest
73 73
 }
74 74
 
75
-func (imr *imageMetaResolver) ResolveImageConfig(ctx context.Context, ref string, opt gw.ResolveImageConfigOpt) (digest.Digest, []byte, error) {
75
+func (imr *imageMetaResolver) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (digest.Digest, []byte, error) {
76 76
 	imr.locker.Lock(ref)
77 77
 	defer imr.locker.Unlock(ref)
78 78
 
... ...
@@ -3,8 +3,8 @@ package llb
3 3
 import (
4 4
 	"context"
5 5
 
6
-	gw "github.com/moby/buildkit/frontend/gateway/client"
7 6
 	digest "github.com/opencontainers/go-digest"
7
+	specs "github.com/opencontainers/image-spec/specs-go/v1"
8 8
 )
9 9
 
10 10
 // WithMetaResolver adds a metadata resolver to an image
... ...
@@ -16,5 +16,11 @@ func WithMetaResolver(mr ImageMetaResolver) ImageOption {
16 16
 
17 17
 // ImageMetaResolver can resolve image config metadata from a reference
18 18
 type ImageMetaResolver interface {
19
-	ResolveImageConfig(ctx context.Context, ref string, opt gw.ResolveImageConfigOpt) (digest.Digest, []byte, error)
19
+	ResolveImageConfig(ctx context.Context, ref string, opt ResolveImageConfigOpt) (digest.Digest, []byte, error)
20
+}
21
+
22
+type ResolveImageConfigOpt struct {
23
+	Platform    *specs.Platform
24
+	ResolveMode string
25
+	LogName     string
20 26
 }
... ...
@@ -9,7 +9,6 @@ import (
9 9
 	"strings"
10 10
 
11 11
 	"github.com/docker/distribution/reference"
12
-	gw "github.com/moby/buildkit/frontend/gateway/client"
13 12
 	"github.com/moby/buildkit/solver/pb"
14 13
 	"github.com/moby/buildkit/util/apicaps"
15 14
 	digest "github.com/opencontainers/go-digest"
... ...
@@ -119,7 +118,7 @@ func Image(ref string, opts ...ImageOption) State {
119 119
 		src.err = err
120 120
 	}
121 121
 	if info.metaResolver != nil {
122
-		_, dt, err := info.metaResolver.ResolveImageConfig(context.TODO(), ref, gw.ResolveImageConfigOpt{
122
+		_, dt, err := info.metaResolver.ResolveImageConfig(context.TODO(), ref, ResolveImageConfigOpt{
123 123
 			Platform:    info.Constraints.Platform,
124 124
 			ResolveMode: info.resolveMode.String(),
125 125
 		})
... ...
@@ -35,6 +35,7 @@ type SolveOpt struct {
35 35
 	SharedKey             string
36 36
 	Frontend              string
37 37
 	FrontendAttrs         map[string]string
38
+	FrontendInputs        map[string]llb.State
38 39
 	CacheExports          []CacheOptionsEntry
39 40
 	CacheImports          []CacheOptionsEntry
40 41
 	Session               []session.Attachable
... ...
@@ -188,16 +189,27 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG
188 188
 		if def != nil {
189 189
 			pbd = def.ToPB()
190 190
 		}
191
+
192
+		frontendInputs := make(map[string]*pb.Definition)
193
+		for key, st := range opt.FrontendInputs {
194
+			def, err := st.Marshal()
195
+			if err != nil {
196
+				return err
197
+			}
198
+			frontendInputs[key] = def.ToPB()
199
+		}
200
+
191 201
 		resp, err := c.controlClient().Solve(ctx, &controlapi.SolveRequest{
192
-			Ref:           ref,
193
-			Definition:    pbd,
194
-			Exporter:      ex.Type,
195
-			ExporterAttrs: ex.Attrs,
196
-			Session:       s.ID(),
197
-			Frontend:      opt.Frontend,
198
-			FrontendAttrs: opt.FrontendAttrs,
199
-			Cache:         cacheOpt.options,
200
-			Entitlements:  opt.AllowedEntitlements,
202
+			Ref:            ref,
203
+			Definition:     pbd,
204
+			Exporter:       ex.Type,
205
+			ExporterAttrs:  ex.Attrs,
206
+			Session:        s.ID(),
207
+			Frontend:       opt.Frontend,
208
+			FrontendAttrs:  opt.FrontendAttrs,
209
+			FrontendInputs: frontendInputs,
210
+			Cache:          cacheOpt.options,
211
+			Entitlements:   opt.AllowedEntitlements,
201 212
 		})
202 213
 		if err != nil {
203 214
 			return errors.Wrap(err, "failed to solve")
... ...
@@ -412,15 +424,15 @@ func parseCacheOptions(opt SolveOpt) (*cacheOptions, error) {
412 412
 			}
413 413
 			cs, err := contentlocal.NewStore(csDir)
414 414
 			if err != nil {
415
-				return nil, err
415
+				logrus.Warning("local cache import at " + csDir + " not found due to err: " + err.Error())
416
+				continue
416 417
 			}
417
-			contentStores["local:"+csDir] = cs
418
-
419 418
 			// if digest is not specified, load from "latest" tag
420 419
 			if attrs["digest"] == "" {
421 420
 				idx, err := ociindex.ReadIndexJSONFileLocked(filepath.Join(csDir, "index.json"))
422 421
 				if err != nil {
423
-					return nil, err
422
+					logrus.Warning("local cache import at " + csDir + " not found due to err: " + err.Error())
423
+					continue
424 424
 				}
425 425
 				for _, m := range idx.Manifests {
426 426
 					if m.Annotations[ocispec.AnnotationRefName] == "latest" {
... ...
@@ -432,6 +444,8 @@ func parseCacheOptions(opt SolveOpt) (*cacheOptions, error) {
432 432
 					return nil, errors.New("local cache importer requires either explicit digest or \"latest\" tag on index.json")
433 433
 				}
434 434
 			}
435
+			contentStores["local:"+csDir] = cs
436
+
435 437
 		}
436 438
 		if im.Type == "registry" {
437 439
 			legacyImportRef := attrs["ref"]
... ...
@@ -274,10 +274,11 @@ func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (*
274 274
 	}
275 275
 
276 276
 	resp, err := c.solver.Solve(ctx, req.Ref, frontend.SolveRequest{
277
-		Frontend:     req.Frontend,
278
-		Definition:   req.Definition,
279
-		FrontendOpt:  req.FrontendAttrs,
280
-		CacheImports: cacheImports,
277
+		Frontend:       req.Frontend,
278
+		Definition:     req.Definition,
279
+		FrontendOpt:    req.FrontendAttrs,
280
+		FrontendInputs: req.FrontendInputs,
281
+		CacheImports:   cacheImports,
281 282
 	}, llbsolver.ExporterRequest{
282 283
 		Exporter:        expi,
283 284
 		CacheExporter:   cacheExporter,
... ...
@@ -128,6 +128,15 @@ func (gwf *GatewayForwarder) Return(ctx context.Context, req *gwapi.ReturnReques
128 128
 	return res, err
129 129
 }
130 130
 
131
+func (gwf *GatewayForwarder) Inputs(ctx context.Context, req *gwapi.InputsRequest) (*gwapi.InputsResponse, error) {
132
+	fwd, err := gwf.lookupForwarder(ctx)
133
+	if err != nil {
134
+		return nil, errors.Wrap(err, "forwarding Inputs")
135
+	}
136
+	res, err := fwd.Inputs(ctx, req)
137
+	return res, err
138
+}
139
+
131 140
 func (gwf *GatewayForwarder) ReadDir(ctx context.Context, req *gwapi.ReadDirRequest) (*gwapi.ReadDirResponse, error) {
132 141
 	fwd, err := gwf.lookupForwarder(ctx)
133 142
 	if err != nil {
... ...
@@ -18,7 +18,7 @@ import (
18 18
 	"github.com/moby/buildkit/executor"
19 19
 	"github.com/moby/buildkit/snapshot"
20 20
 	"github.com/moby/buildkit/solver/pb"
21
-	"github.com/moby/buildkit/util/entitlements"
21
+	"github.com/moby/buildkit/util/entitlements/security"
22 22
 	"github.com/moby/buildkit/util/network"
23 23
 	"github.com/moby/buildkit/util/system"
24 24
 	specs "github.com/opencontainers/runtime-spec/specs-go"
... ...
@@ -38,7 +38,7 @@ func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mou
38 38
 		ctx = namespaces.WithNamespace(ctx, "buildkit")
39 39
 	}
40 40
 	if meta.SecurityMode == pb.SecurityMode_INSECURE {
41
-		opts = append(opts, entitlements.WithInsecureSpec())
41
+		opts = append(opts, security.WithInsecureSpec())
42 42
 	} else if system.SeccompSupported() && meta.SecurityMode == pb.SecurityMode_SANDBOX {
43 43
 		opts = append(opts, seccomp.WithDefaultProfile())
44 44
 	}
... ...
@@ -20,6 +20,7 @@ import (
20 20
 	"github.com/moby/buildkit/exporter/containerimage/exptypes"
21 21
 	"github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb"
22 22
 	"github.com/moby/buildkit/frontend/gateway/client"
23
+	gwpb "github.com/moby/buildkit/frontend/gateway/pb"
23 24
 	"github.com/moby/buildkit/solver/pb"
24 25
 	"github.com/moby/buildkit/util/apicaps"
25 26
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
... ...
@@ -58,6 +59,7 @@ var gitUrlPathWithFragmentSuffix = regexp.MustCompile(`\.git(?:#.+)?$`)
58 58
 func Build(ctx context.Context, c client.Client) (*client.Result, error) {
59 59
 	opts := c.BuildOpts().Opts
60 60
 	caps := c.BuildOpts().LLBCaps
61
+	gwcaps := c.BuildOpts().Caps
61 62
 
62 63
 	marshalOpts := []llb.ConstraintsOpt{llb.WithCaps(caps)}
63 64
 
... ...
@@ -129,7 +131,7 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
129 129
 	fileop := useFileOp(opts, &caps)
130 130
 
131 131
 	var buildContext *llb.State
132
-	isScratchContext := false
132
+	isNotLocalContext := false
133 133
 	if st, ok := detectGitContext(opts[localNameContext], opts[keyContextKeepGitDir]); ok {
134 134
 		if !forceLocalDockerfile {
135 135
 			src = *st
... ...
@@ -191,7 +193,25 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
191 191
 				src = httpContext
192 192
 			}
193 193
 			buildContext = &httpContext
194
-			isScratchContext = true
194
+			isNotLocalContext = true
195
+		}
196
+	} else if (&gwcaps).Supports(gwpb.CapFrontendInputs) == nil {
197
+		inputs, err := c.Inputs(ctx)
198
+		if err != nil {
199
+			return nil, errors.Wrapf(err, "failed to get frontend inputs")
200
+		}
201
+
202
+		if !forceLocalDockerfile {
203
+			inputDockerfile, ok := inputs[DefaultLocalNameDockerfile]
204
+			if ok {
205
+				src = inputDockerfile
206
+			}
207
+		}
208
+
209
+		inputCtx, ok := inputs[DefaultLocalNameContext]
210
+		if ok {
211
+			buildContext = &inputCtx
212
+			isNotLocalContext = true
195 213
 		}
196 214
 	}
197 215
 
... ...
@@ -239,7 +259,7 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
239 239
 		return nil
240 240
 	})
241 241
 	var excludes []string
242
-	if !isScratchContext {
242
+	if !isNotLocalContext {
243 243
 		eg.Go(func() error {
244 244
 			dockerignoreState := buildContext
245 245
 			if dockerignoreState == nil {
... ...
@@ -22,7 +22,6 @@ import (
22 22
 	"github.com/moby/buildkit/frontend/dockerfile/instructions"
23 23
 	"github.com/moby/buildkit/frontend/dockerfile/parser"
24 24
 	"github.com/moby/buildkit/frontend/dockerfile/shell"
25
-	gw "github.com/moby/buildkit/frontend/gateway/client"
26 25
 	"github.com/moby/buildkit/solver/pb"
27 26
 	"github.com/moby/buildkit/util/apicaps"
28 27
 	"github.com/moby/buildkit/util/system"
... ...
@@ -240,7 +239,7 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
240 240
 							prefix += platforms.Format(*platform) + " "
241 241
 						}
242 242
 						prefix += "internal]"
243
-						dgst, dt, err := metaResolver.ResolveImageConfig(ctx, d.stage.BaseName, gw.ResolveImageConfigOpt{
243
+						dgst, dt, err := metaResolver.ResolveImageConfig(ctx, d.stage.BaseName, llb.ResolveImageConfigOpt{
244 244
 							Platform:    platform,
245 245
 							ResolveMode: opt.ImageResolveMode.String(),
246 246
 							LogName:     fmt.Sprintf("%s load metadata for %s", prefix, d.stage.BaseName),
... ...
@@ -346,9 +345,10 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
346 346
 			opt.copyImage = DefaultCopyImage
347 347
 		}
348 348
 
349
-		if err = dispatchOnBuild(d, d.image.Config.OnBuild, opt); err != nil {
349
+		if err = dispatchOnBuildTriggers(d, d.image.Config.OnBuild, opt); err != nil {
350 350
 			return nil, nil, err
351 351
 		}
352
+		d.image.Config.OnBuild = nil
352 353
 
353 354
 		for _, cmd := range d.commands {
354 355
 			if err := dispatch(d, cmd, opt); err != nil {
... ...
@@ -587,7 +587,7 @@ type command struct {
587 587
 	sources []*dispatchState
588 588
 }
589 589
 
590
-func dispatchOnBuild(d *dispatchState, triggers []string, opt dispatchOpt) error {
590
+func dispatchOnBuildTriggers(d *dispatchState, triggers []string, opt dispatchOpt) error {
591 591
 	for _, trigger := range triggers {
592 592
 		ast, err := parser.Parse(strings.NewReader(trigger))
593 593
 		if err != nil {
... ...
@@ -1214,31 +1214,13 @@ func normalizeContextPaths(paths map[string]struct{}) []string {
1214 1214
 		if p == "/" {
1215 1215
 			return nil
1216 1216
 		}
1217
-		pathSlice = append(pathSlice, p)
1217
+		pathSlice = append(pathSlice, path.Join(".", p))
1218 1218
 	}
1219 1219
 
1220
-	toDelete := map[string]struct{}{}
1221
-	for i := range pathSlice {
1222
-		for j := range pathSlice {
1223
-			if i == j {
1224
-				continue
1225
-			}
1226
-			if strings.HasPrefix(pathSlice[j], pathSlice[i]+"/") {
1227
-				delete(paths, pathSlice[j])
1228
-			}
1229
-		}
1230
-	}
1231
-
1232
-	toSort := make([]string, 0, len(paths))
1233
-	for p := range paths {
1234
-		if _, ok := toDelete[p]; !ok {
1235
-			toSort = append(toSort, path.Join(".", p))
1236
-		}
1237
-	}
1238
-	sort.Slice(toSort, func(i, j int) bool {
1239
-		return toSort[i] < toSort[j]
1220
+	sort.Slice(pathSlice, func(i, j int) bool {
1221
+		return pathSlice[i] < pathSlice[j]
1240 1222
 	})
1241
-	return toSort
1223
+	return pathSlice
1242 1224
 }
1243 1225
 
1244 1226
 func proxyEnvFromBuildArgs(args map[string]string) *llb.ProxyEnv {
... ...
@@ -297,7 +297,7 @@ func parseBuildStageName(args []string) (string, error) {
297 297
 	case len(args) == 3 && strings.EqualFold(args[1], "as"):
298 298
 		stageName = strings.ToLower(args[2])
299 299
 		if ok, _ := regexp.MatchString("^[a-z][a-z0-9-_\\.]*$", stageName); !ok {
300
-			return "", errors.Errorf("invalid name for build stage: %q, name can't start with a number or contain symbols", stageName)
300
+			return "", errors.Errorf("invalid name for build stage: %q, name can't start with a number or contain symbols", args[2])
301 301
 		}
302 302
 	case len(args) != 1:
303 303
 		return "", errors.New("FROM requires either one or three arguments")
... ...
@@ -311,6 +311,26 @@ func (sw *shellWord) processDollar() (string, error) {
311 311
 			return fmt.Sprintf("${%s}", name), nil
312 312
 		}
313 313
 		return value, nil
314
+	case '?':
315
+		word, _, err := sw.processStopOn('}')
316
+		if err != nil {
317
+			if sw.scanner.Peek() == scanner.EOF {
318
+				return "", errors.New("syntax error: missing '}'")
319
+			}
320
+			return "", err
321
+		}
322
+		newValue, found := sw.getEnv(name)
323
+		if !found {
324
+			if sw.skipUnsetEnv {
325
+				return fmt.Sprintf("${%s?%s}", name, word), nil
326
+			}
327
+			message := "is not allowed to be unset"
328
+			if word != "" {
329
+				message = word
330
+			}
331
+			return "", errors.Errorf("%s: %s", name, message)
332
+		}
333
+		return newValue, nil
314 334
 	case ':':
315 335
 		// Special ${xx:...} format processing
316 336
 		// Yes it allows for recursive $'s in the ... spot
... ...
@@ -348,6 +368,26 @@ func (sw *shellWord) processDollar() (string, error) {
348 348
 
349 349
 			return newValue, nil
350 350
 
351
+		case '?':
352
+			if !found {
353
+				if sw.skipUnsetEnv {
354
+					return fmt.Sprintf("${%s:%s%s}", name, string(modifier), word), nil
355
+				}
356
+				message := "is not allowed to be unset"
357
+				if word != "" {
358
+					message = word
359
+				}
360
+				return "", errors.Errorf("%s: %s", name, message)
361
+			}
362
+			if newValue == "" {
363
+				message := "is not allowed to be empty"
364
+				if word != "" {
365
+					message = word
366
+				}
367
+				return "", errors.Errorf("%s: %s", name, message)
368
+			}
369
+			return newValue, nil
370
+
351 371
 		default:
352 372
 			return "", errors.Errorf("unsupported modifier (%c) in substitution", modifier)
353 373
 		}
... ...
@@ -6,18 +6,20 @@ import (
6 6
 
7 7
 	"github.com/moby/buildkit/cache"
8 8
 	"github.com/moby/buildkit/client"
9
+	"github.com/moby/buildkit/client/llb"
9 10
 	"github.com/moby/buildkit/executor"
10 11
 	gw "github.com/moby/buildkit/frontend/gateway/client"
12
+	"github.com/moby/buildkit/solver/pb"
11 13
 	digest "github.com/opencontainers/go-digest"
12 14
 )
13 15
 
14 16
 type Frontend interface {
15
-	Solve(ctx context.Context, llb FrontendLLBBridge, opt map[string]string) (*Result, error)
17
+	Solve(ctx context.Context, llb FrontendLLBBridge, opt map[string]string, inputs map[string]*pb.Definition) (*Result, error)
16 18
 }
17 19
 
18 20
 type FrontendLLBBridge interface {
19 21
 	Solve(ctx context.Context, req SolveRequest) (*Result, error)
20
-	ResolveImageConfig(ctx context.Context, ref string, opt gw.ResolveImageConfigOpt) (digest.Digest, []byte, error)
22
+	ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (digest.Digest, []byte, error)
21 23
 	Exec(ctx context.Context, meta executor.Meta, rootfs cache.ImmutableRef, stdin io.ReadCloser, stdout, stderr io.WriteCloser) error
22 24
 }
23 25
 
... ...
@@ -3,6 +3,7 @@ package client
3 3
 import (
4 4
 	"context"
5 5
 
6
+	"github.com/moby/buildkit/client/llb"
6 7
 	"github.com/moby/buildkit/solver/pb"
7 8
 	"github.com/moby/buildkit/util/apicaps"
8 9
 	digest "github.com/opencontainers/go-digest"
... ...
@@ -12,11 +13,13 @@ import (
12 12
 
13 13
 type Client interface {
14 14
 	Solve(ctx context.Context, req SolveRequest) (*Result, error)
15
-	ResolveImageConfig(ctx context.Context, ref string, opt ResolveImageConfigOpt) (digest.Digest, []byte, error)
15
+	ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (digest.Digest, []byte, error)
16 16
 	BuildOpts() BuildOpts
17
+	Inputs(ctx context.Context) (map[string]llb.State, error)
17 18
 }
18 19
 
19 20
 type Reference interface {
21
+	ToState() (llb.State, error)
20 22
 	ReadFile(ctx context.Context, req ReadRequest) ([]byte, error)
21 23
 	StatFile(ctx context.Context, req StatRequest) (*fstypes.Stat, error)
22 24
 	ReadDir(ctx context.Context, req ReadDirRequest) ([]*fstypes.Stat, error)
... ...
@@ -43,10 +46,11 @@ type StatRequest struct {
43 43
 
44 44
 // SolveRequest is same as frontend.SolveRequest but avoiding dependency
45 45
 type SolveRequest struct {
46
-	Definition   *pb.Definition
47
-	Frontend     string
48
-	FrontendOpt  map[string]string
49
-	CacheImports []CacheOptionsEntry
46
+	Definition     *pb.Definition
47
+	Frontend       string
48
+	FrontendOpt    map[string]string
49
+	FrontendInputs map[string]*pb.Definition
50
+	CacheImports   []CacheOptionsEntry
50 51
 }
51 52
 
52 53
 type CacheOptionsEntry struct {
... ...
@@ -68,9 +72,3 @@ type BuildOpts struct {
68 68
 	LLBCaps   apicaps.CapSet
69 69
 	Caps      apicaps.CapSet
70 70
 }
71
-
72
-type ResolveImageConfigOpt struct {
73
-	Platform    *specs.Platform
74
-	ResolveMode string
75
-	LogName     string
76
-}
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"github.com/moby/buildkit/cache"
8 8
 	cacheutil "github.com/moby/buildkit/cache/util"
9 9
 	clienttypes "github.com/moby/buildkit/client"
10
+	"github.com/moby/buildkit/client/llb"
10 11
 	"github.com/moby/buildkit/frontend"
11 12
 	"github.com/moby/buildkit/frontend/gateway/client"
12 13
 	gwpb "github.com/moby/buildkit/frontend/gateway/pb"
... ...
@@ -19,9 +20,10 @@ import (
19 19
 	fstypes "github.com/tonistiigi/fsutil/types"
20 20
 )
21 21
 
22
-func llbBridgeToGatewayClient(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, workerInfos []clienttypes.WorkerInfo) (*bridgeClient, error) {
22
+func llbBridgeToGatewayClient(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, inputs map[string]*opspb.Definition, workerInfos []clienttypes.WorkerInfo) (*bridgeClient, error) {
23 23
 	return &bridgeClient{
24 24
 		opts:              opts,
25
+		inputs:            inputs,
25 26
 		FrontendLLBBridge: llbBridge,
26 27
 		sid:               session.FromContext(ctx),
27 28
 		workerInfos:       workerInfos,
... ...
@@ -33,6 +35,7 @@ type bridgeClient struct {
33 33
 	frontend.FrontendLLBBridge
34 34
 	mu           sync.Mutex
35 35
 	opts         map[string]string
36
+	inputs       map[string]*opspb.Definition
36 37
 	final        map[*ref]struct{}
37 38
 	sid          string
38 39
 	exporterAttr map[string][]byte
... ...
@@ -42,10 +45,11 @@ type bridgeClient struct {
42 42
 
43 43
 func (c *bridgeClient) Solve(ctx context.Context, req client.SolveRequest) (*client.Result, error) {
44 44
 	res, err := c.FrontendLLBBridge.Solve(ctx, frontend.SolveRequest{
45
-		Definition:   req.Definition,
46
-		Frontend:     req.Frontend,
47
-		FrontendOpt:  req.FrontendOpt,
48
-		CacheImports: req.CacheImports,
45
+		Definition:     req.Definition,
46
+		Frontend:       req.Frontend,
47
+		FrontendOpt:    req.FrontendOpt,
48
+		FrontendInputs: req.FrontendInputs,
49
+		CacheImports:   req.CacheImports,
49 50
 	})
50 51
 	if err != nil {
51 52
 		return nil, err
... ...
@@ -54,12 +58,18 @@ func (c *bridgeClient) Solve(ctx context.Context, req client.SolveRequest) (*cli
54 54
 	cRes := &client.Result{}
55 55
 	c.mu.Lock()
56 56
 	for k, r := range res.Refs {
57
-		rr := &ref{r}
57
+		rr, err := newRef(r)
58
+		if err != nil {
59
+			return nil, err
60
+		}
58 61
 		c.refs = append(c.refs, rr)
59 62
 		cRes.AddRef(k, rr)
60 63
 	}
61 64
 	if r := res.Ref; r != nil {
62
-		rr := &ref{r}
65
+		rr, err := newRef(r)
66
+		if err != nil {
67
+			return nil, err
68
+		}
63 69
 		c.refs = append(c.refs, rr)
64 70
 		cRes.SetRef(rr)
65 71
 	}
... ...
@@ -88,6 +98,18 @@ func (c *bridgeClient) BuildOpts() client.BuildOpts {
88 88
 	}
89 89
 }
90 90
 
91
+func (c *bridgeClient) Inputs(ctx context.Context) (map[string]llb.State, error) {
92
+	inputs := make(map[string]llb.State)
93
+	for key, def := range c.inputs {
94
+		defop, err := llb.NewDefinitionOp(def)
95
+		if err != nil {
96
+			return nil, err
97
+		}
98
+		inputs[key] = llb.NewState(defop)
99
+	}
100
+	return inputs, nil
101
+}
102
+
91 103
 func (c *bridgeClient) toFrontendResult(r *client.Result) (*frontend.Result, error) {
92 104
 	if r == nil {
93 105
 		return nil, nil
... ...
@@ -96,14 +118,14 @@ func (c *bridgeClient) toFrontendResult(r *client.Result) (*frontend.Result, err
96 96
 	res := &frontend.Result{}
97 97
 
98 98
 	if r.Refs != nil {
99
-		res.Refs = make(map[string]solver.CachedResult, len(r.Refs))
99
+		res.Refs = make(map[string]solver.ResultProxy, len(r.Refs))
100 100
 		for k, r := range r.Refs {
101 101
 			rr, ok := r.(*ref)
102 102
 			if !ok {
103 103
 				return nil, errors.Errorf("invalid reference type for forward %T", r)
104 104
 			}
105 105
 			c.final[rr] = struct{}{}
106
-			res.Refs[k] = rr.CachedResult
106
+			res.Refs[k] = rr.ResultProxy
107 107
 		}
108 108
 	}
109 109
 	if r := r.Ref; r != nil {
... ...
@@ -112,7 +134,7 @@ func (c *bridgeClient) toFrontendResult(r *client.Result) (*frontend.Result, err
112 112
 			return nil, errors.Errorf("invalid reference type for forward %T", r)
113 113
 		}
114 114
 		c.final[rr] = struct{}{}
115
-		res.Ref = rr.CachedResult
115
+		res.Ref = rr.ResultProxy
116 116
 	}
117 117
 	res.Metadata = r.Metadata
118 118
 
... ...
@@ -130,11 +152,23 @@ func (c *bridgeClient) discard(err error) {
130 130
 }
131 131
 
132 132
 type ref struct {
133
-	solver.CachedResult
133
+	solver.ResultProxy
134
+}
135
+
136
+func newRef(r solver.ResultProxy) (*ref, error) {
137
+	return &ref{ResultProxy: r}, nil
138
+}
139
+
140
+func (r *ref) ToState() (st llb.State, err error) {
141
+	defop, err := llb.NewDefinitionOp(r.Definition())
142
+	if err != nil {
143
+		return st, err
144
+	}
145
+	return llb.NewState(defop), nil
134 146
 }
135 147
 
136 148
 func (r *ref) ReadFile(ctx context.Context, req client.ReadRequest) ([]byte, error) {
137
-	ref, err := r.getImmutableRef()
149
+	ref, err := r.getImmutableRef(ctx)
138 150
 	if err != nil {
139 151
 		return nil, err
140 152
 	}
... ...
@@ -151,7 +185,7 @@ func (r *ref) ReadFile(ctx context.Context, req client.ReadRequest) ([]byte, err
151 151
 }
152 152
 
153 153
 func (r *ref) ReadDir(ctx context.Context, req client.ReadDirRequest) ([]*fstypes.Stat, error) {
154
-	ref, err := r.getImmutableRef()
154
+	ref, err := r.getImmutableRef(ctx)
155 155
 	if err != nil {
156 156
 		return nil, err
157 157
 	}
... ...
@@ -163,17 +197,21 @@ func (r *ref) ReadDir(ctx context.Context, req client.ReadDirRequest) ([]*fstype
163 163
 }
164 164
 
165 165
 func (r *ref) StatFile(ctx context.Context, req client.StatRequest) (*fstypes.Stat, error) {
166
-	ref, err := r.getImmutableRef()
166
+	ref, err := r.getImmutableRef(ctx)
167 167
 	if err != nil {
168 168
 		return nil, err
169 169
 	}
170 170
 	return cacheutil.StatFile(ctx, ref, req.Path)
171 171
 }
172 172
 
173
-func (r *ref) getImmutableRef() (cache.ImmutableRef, error) {
174
-	ref, ok := r.CachedResult.Sys().(*worker.WorkerRef)
173
+func (r *ref) getImmutableRef(ctx context.Context) (cache.ImmutableRef, error) {
174
+	rr, err := r.ResultProxy.Result(ctx)
175
+	if err != nil {
176
+		return nil, err
177
+	}
178
+	ref, ok := rr.Sys().(*worker.WorkerRef)
175 179
 	if !ok {
176
-		return nil, errors.Errorf("invalid ref: %T", r.CachedResult.Sys())
180
+		return nil, errors.Errorf("invalid ref: %T", rr.Sys())
177 181
 	}
178 182
 	return ref.ImmutableRef, nil
179 183
 }
... ...
@@ -5,6 +5,7 @@ import (
5 5
 
6 6
 	"github.com/moby/buildkit/frontend"
7 7
 	"github.com/moby/buildkit/frontend/gateway/client"
8
+	"github.com/moby/buildkit/solver/pb"
8 9
 )
9 10
 
10 11
 func NewGatewayForwarder(w frontend.WorkerInfos, f client.BuildFunc) frontend.Frontend {
... ...
@@ -19,8 +20,8 @@ type GatewayForwarder struct {
19 19
 	f       client.BuildFunc
20 20
 }
21 21
 
22
-func (gf *GatewayForwarder) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string) (retRes *frontend.Result, retErr error) {
23
-	c, err := llbBridgeToGatewayClient(ctx, llbBridge, opts, gf.workers.WorkerInfos())
22
+func (gf *GatewayForwarder) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, inputs map[string]*pb.Definition) (retRes *frontend.Result, retErr error) {
23
+	c, err := llbBridgeToGatewayClient(ctx, llbBridge, opts, inputs, gf.workers.WorkerInfos())
24 24
 	if err != nil {
25 25
 		return nil, err
26 26
 	}
... ...
@@ -21,7 +21,6 @@ import (
21 21
 	"github.com/moby/buildkit/executor"
22 22
 	"github.com/moby/buildkit/exporter/containerimage/exptypes"
23 23
 	"github.com/moby/buildkit/frontend"
24
-	gw "github.com/moby/buildkit/frontend/gateway/client"
25 24
 	pb "github.com/moby/buildkit/frontend/gateway/pb"
26 25
 	"github.com/moby/buildkit/identity"
27 26
 	"github.com/moby/buildkit/session"
... ...
@@ -66,7 +65,7 @@ func filterPrefix(opts map[string]string, pfx string) map[string]string {
66 66
 	return m
67 67
 }
68 68
 
69
-func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string) (*frontend.Result, error) {
69
+func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, inputs map[string]*opspb.Definition) (*frontend.Result, error) {
70 70
 	source, ok := opts[keySource]
71 71
 	if !ok {
72 72
 		return nil, errors.Errorf("no source specified for gateway")
... ...
@@ -82,23 +81,28 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten
82 82
 	if isDevel {
83 83
 		devRes, err := llbBridge.Solve(session.NewContext(ctx, "gateway:"+sid),
84 84
 			frontend.SolveRequest{
85
-				Frontend:    source,
86
-				FrontendOpt: filterPrefix(opts, "gateway-"),
85
+				Frontend:       source,
86
+				FrontendOpt:    filterPrefix(opts, "gateway-"),
87
+				FrontendInputs: inputs,
87 88
 			})
88 89
 		if err != nil {
89 90
 			return nil, err
90 91
 		}
91 92
 		defer func() {
92
-			devRes.EachRef(func(ref solver.CachedResult) error {
93
+			devRes.EachRef(func(ref solver.ResultProxy) error {
93 94
 				return ref.Release(context.TODO())
94 95
 			})
95 96
 		}()
96 97
 		if devRes.Ref == nil {
97 98
 			return nil, errors.Errorf("development gateway didn't return default result")
98 99
 		}
99
-		workerRef, ok := devRes.Ref.Sys().(*worker.WorkerRef)
100
+		res, err := devRes.Ref.Result(ctx)
101
+		if err != nil {
102
+			return nil, err
103
+		}
104
+		workerRef, ok := res.Sys().(*worker.WorkerRef)
100 105
 		if !ok {
101
-			return nil, errors.Errorf("invalid ref: %T", devRes.Ref.Sys())
106
+			return nil, errors.Errorf("invalid ref: %T", res.Sys())
102 107
 		}
103 108
 		rootFS = workerRef.ImmutableRef
104 109
 		config, ok := devRes.Metadata[exptypes.ExporterImageConfigKey]
... ...
@@ -113,7 +117,7 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten
113 113
 			return nil, err
114 114
 		}
115 115
 
116
-		dgst, config, err := llbBridge.ResolveImageConfig(ctx, reference.TagNameOnly(sourceRef).String(), gw.ResolveImageConfigOpt{})
116
+		dgst, config, err := llbBridge.ResolveImageConfig(ctx, reference.TagNameOnly(sourceRef).String(), llb.ResolveImageConfigOpt{})
117 117
 		if err != nil {
118 118
 			return nil, err
119 119
 		}
... ...
@@ -143,7 +147,7 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten
143 143
 			return nil, err
144 144
 		}
145 145
 		defer func() {
146
-			res.EachRef(func(ref solver.CachedResult) error {
146
+			res.EachRef(func(ref solver.ResultProxy) error {
147 147
 				return ref.Release(context.TODO())
148 148
 			})
149 149
 		}()
... ...
@@ -151,14 +155,18 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten
151 151
 			return nil, errors.Errorf("gateway source didn't return default result")
152 152
 
153 153
 		}
154
-		workerRef, ok := res.Ref.Sys().(*worker.WorkerRef)
154
+		r, err := res.Ref.Result(ctx)
155
+		if err != nil {
156
+			return nil, err
157
+		}
158
+		workerRef, ok := r.Sys().(*worker.WorkerRef)
155 159
 		if !ok {
156
-			return nil, errors.Errorf("invalid ref: %T", res.Ref.Sys())
160
+			return nil, errors.Errorf("invalid ref: %T", r.Sys())
157 161
 		}
158 162
 		rootFS = workerRef.ImmutableRef
159 163
 	}
160 164
 
161
-	lbf, ctx, err := newLLBBridgeForwarder(ctx, llbBridge, gf.workers)
165
+	lbf, ctx, err := newLLBBridgeForwarder(ctx, llbBridge, gf.workers, inputs)
162 166
 	defer lbf.conn.Close()
163 167
 	if err != nil {
164 168
 		return nil, err
... ...
@@ -233,7 +241,7 @@ func (lbf *llbBridgeForwarder) Discard() {
233 233
 	for id, r := range lbf.refs {
234 234
 		if lbf.err == nil && lbf.result != nil {
235 235
 			keep := false
236
-			lbf.result.EachRef(func(r2 solver.CachedResult) error {
236
+			lbf.result.EachRef(func(r2 solver.ResultProxy) error {
237 237
 				if r == r2 {
238 238
 					keep = true
239 239
 				}
... ...
@@ -285,21 +293,22 @@ func (lbf *llbBridgeForwarder) Result() (*frontend.Result, error) {
285 285
 	return lbf.result, nil
286 286
 }
287 287
 
288
-func NewBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers frontend.WorkerInfos) *llbBridgeForwarder {
288
+func NewBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers frontend.WorkerInfos, inputs map[string]*opspb.Definition) *llbBridgeForwarder {
289 289
 	lbf := &llbBridgeForwarder{
290 290
 		callCtx:   ctx,
291 291
 		llbBridge: llbBridge,
292
-		refs:      map[string]solver.CachedResult{},
292
+		refs:      map[string]solver.ResultProxy{},
293 293
 		doneCh:    make(chan struct{}),
294 294
 		pipe:      newPipe(),
295 295
 		workers:   workers,
296
+		inputs:    inputs,
296 297
 	}
297 298
 	return lbf
298 299
 }
299 300
 
300
-func newLLBBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers frontend.WorkerInfos) (*llbBridgeForwarder, context.Context, error) {
301
+func newLLBBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers frontend.WorkerInfos, inputs map[string]*opspb.Definition) (*llbBridgeForwarder, context.Context, error) {
301 302
 	ctx, cancel := context.WithCancel(ctx)
302
-	lbf := NewBridgeForwarder(ctx, llbBridge, workers)
303
+	lbf := NewBridgeForwarder(ctx, llbBridge, workers, inputs)
303 304
 	server := grpc.NewServer()
304 305
 	grpc_health_v1.RegisterHealthServer(server, health.NewServer())
305 306
 	pb.RegisterLLBBridgeServer(server, lbf)
... ...
@@ -380,7 +389,7 @@ type llbBridgeForwarder struct {
380 380
 	mu        sync.Mutex
381 381
 	callCtx   context.Context
382 382
 	llbBridge frontend.FrontendLLBBridge
383
-	refs      map[string]solver.CachedResult
383
+	refs      map[string]solver.ResultProxy
384 384
 	// lastRef      solver.CachedResult
385 385
 	// lastRefs     map[string]solver.CachedResult
386 386
 	// err          error
... ...
@@ -389,6 +398,7 @@ type llbBridgeForwarder struct {
389 389
 	err               error
390 390
 	exporterAttr      map[string][]byte
391 391
 	workers           frontend.WorkerInfos
392
+	inputs            map[string]*opspb.Definition
392 393
 	isErrServerClosed bool
393 394
 	*pipe
394 395
 }
... ...
@@ -405,7 +415,7 @@ func (lbf *llbBridgeForwarder) ResolveImageConfig(ctx context.Context, req *pb.R
405 405
 			OSFeatures:   p.OSFeatures,
406 406
 		}
407 407
 	}
408
-	dgst, dt, err := lbf.llbBridge.ResolveImageConfig(ctx, req.Ref, gw.ResolveImageConfigOpt{
408
+	dgst, dt, err := lbf.llbBridge.ResolveImageConfig(ctx, req.Ref, llb.ResolveImageConfigOpt{
409 409
 		Platform:    platform,
410 410
 		ResolveMode: req.ResolveMode,
411 411
 		LogName:     req.LogName,
... ...
@@ -444,12 +454,14 @@ func (lbf *llbBridgeForwarder) Solve(ctx context.Context, req *pb.SolveRequest)
444 444
 			Attrs: e.Attrs,
445 445
 		})
446 446
 	}
447
+
447 448
 	ctx = tracing.ContextWithSpanFromContext(ctx, lbf.callCtx)
448 449
 	res, err := lbf.llbBridge.Solve(ctx, frontend.SolveRequest{
449
-		Definition:   req.Definition,
450
-		Frontend:     req.Frontend,
451
-		FrontendOpt:  req.FrontendOpt,
452
-		CacheImports: cacheImports,
450
+		Definition:     req.Definition,
451
+		Frontend:       req.Frontend,
452
+		FrontendOpt:    req.FrontendOpt,
453
+		FrontendInputs: req.FrontendInputs,
454
+		CacheImports:   cacheImports,
453 455
 	})
454 456
 	if err != nil {
455 457
 		return nil, err
... ...
@@ -466,6 +478,7 @@ func (lbf *llbBridgeForwarder) Solve(ctx context.Context, req *pb.SolveRequest)
466 466
 	lbf.mu.Lock()
467 467
 	if res.Refs != nil {
468 468
 		ids := make(map[string]string, len(res.Refs))
469
+		defs := make(map[string]*opspb.Definition, len(res.Refs))
469 470
 		for k, ref := range res.Refs {
470 471
 			id := identity.NewID()
471 472
 			if ref == nil {
... ...
@@ -474,17 +487,36 @@ func (lbf *llbBridgeForwarder) Solve(ctx context.Context, req *pb.SolveRequest)
474 474
 				lbf.refs[id] = ref
475 475
 			}
476 476
 			ids[k] = id
477
+			defs[k] = ref.Definition()
478
+		}
479
+
480
+		if req.AllowResultArrayRef {
481
+			refMap := make(map[string]*pb.Ref, len(res.Refs))
482
+			for k, id := range ids {
483
+				refMap[k] = &pb.Ref{Id: id, Def: defs[k]}
484
+			}
485
+			pbRes.Result = &pb.Result_Refs{Refs: &pb.RefMap{Refs: refMap}}
486
+		} else {
487
+			pbRes.Result = &pb.Result_RefsDeprecated{RefsDeprecated: &pb.RefMapDeprecated{Refs: ids}}
477 488
 		}
478
-		pbRes.Result = &pb.Result_Refs{Refs: &pb.RefMap{Refs: ids}}
479 489
 	} else {
490
+		ref := res.Ref
480 491
 		id := identity.NewID()
481
-		if res.Ref == nil {
492
+
493
+		var def *opspb.Definition
494
+		if ref == nil {
482 495
 			id = ""
483 496
 		} else {
484
-			lbf.refs[id] = res.Ref
497
+			def = ref.Definition()
498
+			lbf.refs[id] = ref
485 499
 		}
486 500
 		defaultID = id
487
-		pbRes.Result = &pb.Result_Ref{Ref: id}
501
+
502
+		if req.AllowResultArrayRef {
503
+			pbRes.Result = &pb.Result_Ref{Ref: &pb.Ref{Id: id, Def: def}}
504
+		} else {
505
+			pbRes.Result = &pb.Result_RefDeprecated{RefDeprecated: id}
506
+		}
488 507
 	}
489 508
 	lbf.mu.Unlock()
490 509
 
... ...
@@ -528,9 +560,13 @@ func (lbf *llbBridgeForwarder) ReadFile(ctx context.Context, req *pb.ReadFileReq
528 528
 	if ref == nil {
529 529
 		return nil, errors.Wrapf(os.ErrNotExist, "%s not found", req.FilePath)
530 530
 	}
531
-	workerRef, ok := ref.Sys().(*worker.WorkerRef)
531
+	r, err := ref.Result(ctx)
532
+	if err != nil {
533
+		return nil, err
534
+	}
535
+	workerRef, ok := r.Sys().(*worker.WorkerRef)
532 536
 	if !ok {
533
-		return nil, errors.Errorf("invalid ref: %T", ref.Sys())
537
+		return nil, errors.Errorf("invalid ref: %T", r.Sys())
534 538
 	}
535 539
 
536 540
 	newReq := cacheutil.ReadRequest{
... ...
@@ -562,9 +598,13 @@ func (lbf *llbBridgeForwarder) ReadDir(ctx context.Context, req *pb.ReadDirReque
562 562
 	if ref == nil {
563 563
 		return nil, errors.Wrapf(os.ErrNotExist, "%s not found", req.DirPath)
564 564
 	}
565
-	workerRef, ok := ref.Sys().(*worker.WorkerRef)
565
+	r, err := ref.Result(ctx)
566
+	if err != nil {
567
+		return nil, err
568
+	}
569
+	workerRef, ok := r.Sys().(*worker.WorkerRef)
566 570
 	if !ok {
567
-		return nil, errors.Errorf("invalid ref: %T", ref.Sys())
571
+		return nil, errors.Errorf("invalid ref: %T", r.Sys())
568 572
 	}
569 573
 
570 574
 	newReq := cacheutil.ReadDirRequest{
... ...
@@ -590,9 +630,13 @@ func (lbf *llbBridgeForwarder) StatFile(ctx context.Context, req *pb.StatFileReq
590 590
 	if ref == nil {
591 591
 		return nil, errors.Wrapf(os.ErrNotExist, "%s not found", req.Path)
592 592
 	}
593
-	workerRef, ok := ref.Sys().(*worker.WorkerRef)
593
+	r, err := ref.Result(ctx)
594
+	if err != nil {
595
+		return nil, err
596
+	}
597
+	workerRef, ok := r.Sys().(*worker.WorkerRef)
594 598
 	if !ok {
595
-		return nil, errors.Errorf("invalid ref: %T", ref.Sys())
599
+		return nil, errors.Errorf("invalid ref: %T", r.Sys())
596 600
 	}
597 601
 
598 602
 	st, err := cacheutil.StatFile(ctx, workerRef.ImmutableRef, req.Path)
... ...
@@ -635,16 +679,32 @@ func (lbf *llbBridgeForwarder) Return(ctx context.Context, in *pb.ReturnRequest)
635 635
 		}
636 636
 
637 637
 		switch res := in.Result.Result.(type) {
638
+		case *pb.Result_RefDeprecated:
639
+			ref, err := lbf.convertRef(res.RefDeprecated)
640
+			if err != nil {
641
+				return nil, err
642
+			}
643
+			r.Ref = ref
644
+		case *pb.Result_RefsDeprecated:
645
+			m := map[string]solver.ResultProxy{}
646
+			for k, id := range res.RefsDeprecated.Refs {
647
+				ref, err := lbf.convertRef(id)
648
+				if err != nil {
649
+					return nil, err
650
+				}
651
+				m[k] = ref
652
+			}
653
+			r.Refs = m
638 654
 		case *pb.Result_Ref:
639
-			ref, err := lbf.convertRef(res.Ref)
655
+			ref, err := lbf.convertRef(res.Ref.Id)
640 656
 			if err != nil {
641 657
 				return nil, err
642 658
 			}
643 659
 			r.Ref = ref
644 660
 		case *pb.Result_Refs:
645
-			m := map[string]solver.CachedResult{}
646
-			for k, v := range res.Refs.Refs {
647
-				ref, err := lbf.convertRef(v)
661
+			m := map[string]solver.ResultProxy{}
662
+			for k, ref := range res.Refs.Refs {
663
+				ref, err := lbf.convertRef(ref.Id)
648 664
 				if err != nil {
649 665
 					return nil, err
650 666
 				}
... ...
@@ -656,16 +716,25 @@ func (lbf *llbBridgeForwarder) Return(ctx context.Context, in *pb.ReturnRequest)
656 656
 	}
657 657
 }
658 658
 
659
-func (lbf *llbBridgeForwarder) convertRef(id string) (solver.CachedResult, error) {
659
+func (lbf *llbBridgeForwarder) Inputs(ctx context.Context, in *pb.InputsRequest) (*pb.InputsResponse, error) {
660
+	return &pb.InputsResponse{
661
+		Definitions: lbf.inputs,
662
+	}, nil
663
+}
664
+
665
+func (lbf *llbBridgeForwarder) convertRef(id string) (solver.ResultProxy, error) {
660 666
 	if id == "" {
661 667
 		return nil, nil
662 668
 	}
669
+
663 670
 	lbf.mu.Lock()
664 671
 	defer lbf.mu.Unlock()
672
+
665 673
 	r, ok := lbf.refs[id]
666 674
 	if !ok {
667 675
 		return nil, errors.Errorf("return reference %s not found", id)
668 676
 	}
677
+
669 678
 	return r, nil
670 679
 }
671 680
 
... ...
@@ -10,6 +10,7 @@ import (
10 10
 	"time"
11 11
 
12 12
 	"github.com/gogo/googleapis/google/rpc"
13
+	"github.com/moby/buildkit/client/llb"
13 14
 	"github.com/moby/buildkit/frontend/gateway/client"
14 15
 	pb "github.com/moby/buildkit/frontend/gateway/pb"
15 16
 	opspb "github.com/moby/buildkit/solver/pb"
... ...
@@ -68,15 +69,15 @@ func current() (GrpcClient, error) {
68 68
 	return New(ctx, opts(), sessionID(), product(), pb.NewLLBBridgeClient(conn), workers())
69 69
 }
70 70
 
71
-func convertRef(ref client.Reference) (string, error) {
71
+func convertRef(ref client.Reference) (*pb.Ref, error) {
72 72
 	if ref == nil {
73
-		return "", nil
73
+		return &pb.Ref{}, nil
74 74
 	}
75 75
 	r, ok := ref.(*reference)
76 76
 	if !ok {
77
-		return "", errors.Errorf("invalid return reference type %T", ref)
77
+		return nil, errors.Errorf("invalid return reference type %T", ref)
78 78
 	}
79
-	return r.id, nil
79
+	return &pb.Ref{Id: r.id, Def: r.def}, nil
80 80
 }
81 81
 
82 82
 func RunFromEnvironment(ctx context.Context, f client.BuildFunc) error {
... ...
@@ -105,22 +106,43 @@ func (c *grpcClient) Run(ctx context.Context, f client.BuildFunc) (retError erro
105 105
 					Metadata: res.Metadata,
106 106
 				}
107 107
 				if res.Refs != nil {
108
-					m := map[string]string{}
109
-					for k, r := range res.Refs {
110
-						id, err := convertRef(r)
111
-						if err != nil {
112
-							retError = err
113
-							continue
108
+					if c.caps.Supports(pb.CapProtoRefArray) == nil {
109
+						m := map[string]*pb.Ref{}
110
+						for k, r := range res.Refs {
111
+							pbRef, err := convertRef(r)
112
+							if err != nil {
113
+								retError = err
114
+								continue
115
+							}
116
+							m[k] = pbRef
114 117
 						}
115
-						m[k] = id
118
+						pbRes.Result = &pb.Result_Refs{Refs: &pb.RefMap{Refs: m}}
119
+					} else {
120
+						// Server doesn't support the new wire format for refs, so we construct
121
+						// a deprecated result ref map.
122
+						m := map[string]string{}
123
+						for k, r := range res.Refs {
124
+							pbRef, err := convertRef(r)
125
+							if err != nil {
126
+								retError = err
127
+								continue
128
+							}
129
+							m[k] = pbRef.Id
130
+						}
131
+						pbRes.Result = &pb.Result_RefsDeprecated{RefsDeprecated: &pb.RefMapDeprecated{Refs: m}}
116 132
 					}
117
-					pbRes.Result = &pb.Result_Refs{Refs: &pb.RefMap{Refs: m}}
118 133
 				} else {
119
-					id, err := convertRef(res.Ref)
134
+					pbRef, err := convertRef(res.Ref)
120 135
 					if err != nil {
121 136
 						retError = err
122 137
 					} else {
123
-						pbRes.Result = &pb.Result_Ref{Ref: id}
138
+						if c.caps.Supports(pb.CapProtoRefArray) == nil {
139
+							pbRes.Result = &pb.Result_Ref{Ref: pbRef}
140
+						} else {
141
+							// Server doesn't support the new wire format for refs, so we construct
142
+							// a deprecated result ref.
143
+							pbRes.Result = &pb.Result_RefDeprecated{RefDeprecated: pbRef.Id}
144
+						}
124 145
 					}
125 146
 				}
126 147
 				if retError == nil {
... ...
@@ -280,10 +302,12 @@ func (c *grpcClient) Solve(ctx context.Context, creq client.SolveRequest) (*clie
280 280
 	}
281 281
 
282 282
 	req := &pb.SolveRequest{
283
-		Definition:        creq.Definition,
284
-		Frontend:          creq.Frontend,
285
-		FrontendOpt:       creq.FrontendOpt,
286
-		AllowResultReturn: true,
283
+		Definition:          creq.Definition,
284
+		Frontend:            creq.Frontend,
285
+		FrontendOpt:         creq.FrontendOpt,
286
+		FrontendInputs:      creq.FrontendInputs,
287
+		AllowResultReturn:   true,
288
+		AllowResultArrayRef: true,
287 289
 		// old API
288 290
 		ImportCacheRefsDeprecated: legacyRegistryCacheImports,
289 291
 		// new API
... ...
@@ -310,25 +334,44 @@ func (c *grpcClient) Solve(ctx context.Context, creq client.SolveRequest) (*clie
310 310
 	} else {
311 311
 		res.Metadata = resp.Result.Metadata
312 312
 		switch pbRes := resp.Result.Result.(type) {
313
-		case *pb.Result_Ref:
314
-			if id := pbRes.Ref; id != "" {
313
+		case *pb.Result_RefDeprecated:
314
+			if id := pbRes.RefDeprecated; id != "" {
315 315
 				res.SetRef(&reference{id: id, c: c})
316 316
 			}
317
-		case *pb.Result_Refs:
318
-			for k, v := range pbRes.Refs.Refs {
317
+		case *pb.Result_RefsDeprecated:
318
+			for k, v := range pbRes.RefsDeprecated.Refs {
319 319
 				ref := &reference{id: v, c: c}
320 320
 				if v == "" {
321 321
 					ref = nil
322 322
 				}
323 323
 				res.AddRef(k, ref)
324 324
 			}
325
+		case *pb.Result_Ref:
326
+			if pbRes.Ref.Id != "" {
327
+				ref, err := newReference(c, pbRes.Ref)
328
+				if err != nil {
329
+					return nil, err
330
+				}
331
+				res.SetRef(ref)
332
+			}
333
+		case *pb.Result_Refs:
334
+			for k, v := range pbRes.Refs.Refs {
335
+				var ref *reference
336
+				if v.Id != "" {
337
+					ref, err = newReference(c, v)
338
+					if err != nil {
339
+						return nil, err
340
+					}
341
+				}
342
+				res.AddRef(k, ref)
343
+			}
325 344
 		}
326 345
 	}
327 346
 
328 347
 	return res, nil
329 348
 }
330 349
 
331
-func (c *grpcClient) ResolveImageConfig(ctx context.Context, ref string, opt client.ResolveImageConfigOpt) (digest.Digest, []byte, error) {
350
+func (c *grpcClient) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (digest.Digest, []byte, error) {
332 351
 	var p *opspb.Platform
333 352
 	if platform := opt.Platform; platform != nil {
334 353
 		p = &opspb.Platform{
... ...
@@ -357,9 +400,56 @@ func (c *grpcClient) BuildOpts() client.BuildOpts {
357 357
 	}
358 358
 }
359 359
 
360
+func (c *grpcClient) Inputs(ctx context.Context) (map[string]llb.State, error) {
361
+	err := c.caps.Supports(pb.CapFrontendInputs)
362
+	if err != nil {
363
+		return nil, err
364
+	}
365
+
366
+	resp, err := c.client.Inputs(ctx, &pb.InputsRequest{})
367
+	if err != nil {
368
+		return nil, err
369
+	}
370
+
371
+	inputs := make(map[string]llb.State)
372
+	for key, def := range resp.Definitions {
373
+		op, err := llb.NewDefinitionOp(def)
374
+		if err != nil {
375
+			return nil, err
376
+		}
377
+		inputs[key] = llb.NewState(op)
378
+	}
379
+	return inputs, nil
380
+
381
+}
382
+
360 383
 type reference struct {
361
-	id string
362
-	c  *grpcClient
384
+	c      *grpcClient
385
+	id     string
386
+	def    *opspb.Definition
387
+	output llb.Output
388
+}
389
+
390
+func newReference(c *grpcClient, ref *pb.Ref) (*reference, error) {
391
+	return &reference{c: c, id: ref.Id, def: ref.Def}, nil
392
+}
393
+
394
+func (r *reference) ToState() (st llb.State, err error) {
395
+	err = r.c.caps.Supports(pb.CapReferenceOutput)
396
+	if err != nil {
397
+		return st, err
398
+	}
399
+
400
+	if r.def == nil {
401
+		return st, errors.Errorf("gateway did not return reference with definition")
402
+	}
403
+
404
+	defop, err := llb.NewDefinitionOp(r.def)
405
+	if err != nil {
406
+		return st, err
407
+	}
408
+
409
+	return llb.NewState(defop), nil
363 410
 }
364 411
 
365 412
 func (r *reference) ReadFile(ctx context.Context, req client.ReadRequest) ([]byte, error) {
... ...
@@ -19,6 +19,19 @@ const (
19 19
 	CapReadDir                 apicaps.CapID = "readdir"
20 20
 	CapStatFile                apicaps.CapID = "statfile"
21 21
 	CapImportCaches            apicaps.CapID = "importcaches"
22
+
23
+	// CapProtoRefArray is a capability to return arrays of refs instead of single
24
+	// refs. This capability is only for the wire format change and shouldn't be
25
+	// used in frontends for feature detection.
26
+	CapProtoRefArray apicaps.CapID = "proto.refarray"
27
+
28
+	// CapReferenceOutput is a capability to use a reference of a solved result as
29
+	// an llb.Output.
30
+	CapReferenceOutput apicaps.CapID = "reference.output"
31
+
32
+	// CapFrontendInputs is a capability to request frontend inputs from the
33
+	// LLBBridge GRPC server.
34
+	CapFrontendInputs apicaps.CapID = "frontend.inputs"
22 35
 )
23 36
 
24 37
 func init() {
... ...
@@ -92,4 +105,25 @@ func init() {
92 92
 		Enabled: true,
93 93
 		Status:  apicaps.CapStatusExperimental,
94 94
 	})
95
+
96
+	Caps.Init(apicaps.Cap{
97
+		ID:      CapProtoRefArray,
98
+		Name:    "wire format ref arrays",
99
+		Enabled: true,
100
+		Status:  apicaps.CapStatusExperimental,
101
+	})
102
+
103
+	Caps.Init(apicaps.Cap{
104
+		ID:      CapReferenceOutput,
105
+		Name:    "reference output",
106
+		Enabled: true,
107
+		Status:  apicaps.CapStatusExperimental,
108
+	})
109
+
110
+	Caps.Init(apicaps.Cap{
111
+		ID:      CapFrontendInputs,
112
+		Name:    "frontend inputs",
113
+		Enabled: true,
114
+		Status:  apicaps.CapStatusExperimental,
115
+	})
95 116
 }
... ...
@@ -35,6 +35,8 @@ const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
35 35
 
36 36
 type Result struct {
37 37
 	// Types that are valid to be assigned to Result:
38
+	//	*Result_RefDeprecated
39
+	//	*Result_RefsDeprecated
38 40
 	//	*Result_Ref
39 41
 	//	*Result_Refs
40 42
 	Result               isResult_Result   `protobuf_oneof:"result"`
... ...
@@ -48,7 +50,7 @@ func (m *Result) Reset()         { *m = Result{} }
48 48
 func (m *Result) String() string { return proto.CompactTextString(m) }
49 49
 func (*Result) ProtoMessage()    {}
50 50
 func (*Result) Descriptor() ([]byte, []int) {
51
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{0}
51
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{0}
52 52
 }
53 53
 func (m *Result) XXX_Unmarshal(b []byte) error {
54 54
 	return m.Unmarshal(b)
... ...
@@ -83,15 +85,23 @@ type isResult_Result interface {
83 83
 	Size() int
84 84
 }
85 85
 
86
+type Result_RefDeprecated struct {
87
+	RefDeprecated string `protobuf:"bytes,1,opt,name=refDeprecated,proto3,oneof"`
88
+}
89
+type Result_RefsDeprecated struct {
90
+	RefsDeprecated *RefMapDeprecated `protobuf:"bytes,2,opt,name=refsDeprecated,proto3,oneof"`
91
+}
86 92
 type Result_Ref struct {
87
-	Ref string `protobuf:"bytes,1,opt,name=ref,proto3,oneof"`
93
+	Ref *Ref `protobuf:"bytes,3,opt,name=ref,proto3,oneof"`
88 94
 }
89 95
 type Result_Refs struct {
90
-	Refs *RefMap `protobuf:"bytes,2,opt,name=refs,proto3,oneof"`
96
+	Refs *RefMap `protobuf:"bytes,4,opt,name=refs,proto3,oneof"`
91 97
 }
92 98
 
93
-func (*Result_Ref) isResult_Result()  {}
94
-func (*Result_Refs) isResult_Result() {}
99
+func (*Result_RefDeprecated) isResult_Result()  {}
100
+func (*Result_RefsDeprecated) isResult_Result() {}
101
+func (*Result_Ref) isResult_Result()            {}
102
+func (*Result_Refs) isResult_Result()           {}
95 103
 
96 104
 func (m *Result) GetResult() isResult_Result {
97 105
 	if m != nil {
... ...
@@ -100,11 +110,25 @@ func (m *Result) GetResult() isResult_Result {
100 100
 	return nil
101 101
 }
102 102
 
103
-func (m *Result) GetRef() string {
103
+func (m *Result) GetRefDeprecated() string {
104
+	if x, ok := m.GetResult().(*Result_RefDeprecated); ok {
105
+		return x.RefDeprecated
106
+	}
107
+	return ""
108
+}
109
+
110
+func (m *Result) GetRefsDeprecated() *RefMapDeprecated {
111
+	if x, ok := m.GetResult().(*Result_RefsDeprecated); ok {
112
+		return x.RefsDeprecated
113
+	}
114
+	return nil
115
+}
116
+
117
+func (m *Result) GetRef() *Ref {
104 118
 	if x, ok := m.GetResult().(*Result_Ref); ok {
105 119
 		return x.Ref
106 120
 	}
107
-	return ""
121
+	return nil
108 122
 }
109 123
 
110 124
 func (m *Result) GetRefs() *RefMap {
... ...
@@ -124,6 +148,8 @@ func (m *Result) GetMetadata() map[string][]byte {
124 124
 // XXX_OneofFuncs is for the internal use of the proto package.
125 125
 func (*Result) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
126 126
 	return _Result_OneofMarshaler, _Result_OneofUnmarshaler, _Result_OneofSizer, []interface{}{
127
+		(*Result_RefDeprecated)(nil),
128
+		(*Result_RefsDeprecated)(nil),
127 129
 		(*Result_Ref)(nil),
128 130
 		(*Result_Refs)(nil),
129 131
 	}
... ...
@@ -133,11 +159,21 @@ func _Result_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
133 133
 	m := msg.(*Result)
134 134
 	// result
135 135
 	switch x := m.Result.(type) {
136
-	case *Result_Ref:
136
+	case *Result_RefDeprecated:
137 137
 		_ = b.EncodeVarint(1<<3 | proto.WireBytes)
138
-		_ = b.EncodeStringBytes(x.Ref)
139
-	case *Result_Refs:
138
+		_ = b.EncodeStringBytes(x.RefDeprecated)
139
+	case *Result_RefsDeprecated:
140 140
 		_ = b.EncodeVarint(2<<3 | proto.WireBytes)
141
+		if err := b.EncodeMessage(x.RefsDeprecated); err != nil {
142
+			return err
143
+		}
144
+	case *Result_Ref:
145
+		_ = b.EncodeVarint(3<<3 | proto.WireBytes)
146
+		if err := b.EncodeMessage(x.Ref); err != nil {
147
+			return err
148
+		}
149
+	case *Result_Refs:
150
+		_ = b.EncodeVarint(4<<3 | proto.WireBytes)
141 151
 		if err := b.EncodeMessage(x.Refs); err != nil {
142 152
 			return err
143 153
 		}
... ...
@@ -151,14 +187,30 @@ func _Result_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
151 151
 func _Result_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
152 152
 	m := msg.(*Result)
153 153
 	switch tag {
154
-	case 1: // result.ref
154
+	case 1: // result.refDeprecated
155 155
 		if wire != proto.WireBytes {
156 156
 			return true, proto.ErrInternalBadWireType
157 157
 		}
158 158
 		x, err := b.DecodeStringBytes()
159
-		m.Result = &Result_Ref{x}
159
+		m.Result = &Result_RefDeprecated{x}
160 160
 		return true, err
161
-	case 2: // result.refs
161
+	case 2: // result.refsDeprecated
162
+		if wire != proto.WireBytes {
163
+			return true, proto.ErrInternalBadWireType
164
+		}
165
+		msg := new(RefMapDeprecated)
166
+		err := b.DecodeMessage(msg)
167
+		m.Result = &Result_RefsDeprecated{msg}
168
+		return true, err
169
+	case 3: // result.ref
170
+		if wire != proto.WireBytes {
171
+			return true, proto.ErrInternalBadWireType
172
+		}
173
+		msg := new(Ref)
174
+		err := b.DecodeMessage(msg)
175
+		m.Result = &Result_Ref{msg}
176
+		return true, err
177
+	case 4: // result.refs
162 178
 		if wire != proto.WireBytes {
163 179
 			return true, proto.ErrInternalBadWireType
164 180
 		}
... ...
@@ -175,10 +227,20 @@ func _Result_OneofSizer(msg proto.Message) (n int) {
175 175
 	m := msg.(*Result)
176 176
 	// result
177 177
 	switch x := m.Result.(type) {
178
+	case *Result_RefDeprecated:
179
+		n += 1 // tag and wire
180
+		n += proto.SizeVarint(uint64(len(x.RefDeprecated)))
181
+		n += len(x.RefDeprecated)
182
+	case *Result_RefsDeprecated:
183
+		s := proto.Size(x.RefsDeprecated)
184
+		n += 1 // tag and wire
185
+		n += proto.SizeVarint(uint64(s))
186
+		n += s
178 187
 	case *Result_Ref:
188
+		s := proto.Size(x.Ref)
179 189
 		n += 1 // tag and wire
180
-		n += proto.SizeVarint(uint64(len(x.Ref)))
181
-		n += len(x.Ref)
190
+		n += proto.SizeVarint(uint64(s))
191
+		n += s
182 192
 	case *Result_Refs:
183 193
 		s := proto.Size(x.Refs)
184 194
 		n += 1 // tag and wire
... ...
@@ -191,18 +253,120 @@ func _Result_OneofSizer(msg proto.Message) (n int) {
191 191
 	return n
192 192
 }
193 193
 
194
-type RefMap struct {
194
+type RefMapDeprecated struct {
195 195
 	Refs                 map[string]string `protobuf:"bytes,1,rep,name=refs,proto3" json:"refs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
196 196
 	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
197 197
 	XXX_unrecognized     []byte            `json:"-"`
198 198
 	XXX_sizecache        int32             `json:"-"`
199 199
 }
200 200
 
201
+func (m *RefMapDeprecated) Reset()         { *m = RefMapDeprecated{} }
202
+func (m *RefMapDeprecated) String() string { return proto.CompactTextString(m) }
203
+func (*RefMapDeprecated) ProtoMessage()    {}
204
+func (*RefMapDeprecated) Descriptor() ([]byte, []int) {
205
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{1}
206
+}
207
+func (m *RefMapDeprecated) XXX_Unmarshal(b []byte) error {
208
+	return m.Unmarshal(b)
209
+}
210
+func (m *RefMapDeprecated) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
211
+	if deterministic {
212
+		return xxx_messageInfo_RefMapDeprecated.Marshal(b, m, deterministic)
213
+	} else {
214
+		b = b[:cap(b)]
215
+		n, err := m.MarshalTo(b)
216
+		if err != nil {
217
+			return nil, err
218
+		}
219
+		return b[:n], nil
220
+	}
221
+}
222
+func (dst *RefMapDeprecated) XXX_Merge(src proto.Message) {
223
+	xxx_messageInfo_RefMapDeprecated.Merge(dst, src)
224
+}
225
+func (m *RefMapDeprecated) XXX_Size() int {
226
+	return m.Size()
227
+}
228
+func (m *RefMapDeprecated) XXX_DiscardUnknown() {
229
+	xxx_messageInfo_RefMapDeprecated.DiscardUnknown(m)
230
+}
231
+
232
+var xxx_messageInfo_RefMapDeprecated proto.InternalMessageInfo
233
+
234
+func (m *RefMapDeprecated) GetRefs() map[string]string {
235
+	if m != nil {
236
+		return m.Refs
237
+	}
238
+	return nil
239
+}
240
+
241
+type Ref struct {
242
+	Id                   string         `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
243
+	Def                  *pb.Definition `protobuf:"bytes,2,opt,name=def,proto3" json:"def,omitempty"`
244
+	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
245
+	XXX_unrecognized     []byte         `json:"-"`
246
+	XXX_sizecache        int32          `json:"-"`
247
+}
248
+
249
+func (m *Ref) Reset()         { *m = Ref{} }
250
+func (m *Ref) String() string { return proto.CompactTextString(m) }
251
+func (*Ref) ProtoMessage()    {}
252
+func (*Ref) Descriptor() ([]byte, []int) {
253
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{2}
254
+}
255
+func (m *Ref) XXX_Unmarshal(b []byte) error {
256
+	return m.Unmarshal(b)
257
+}
258
+func (m *Ref) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
259
+	if deterministic {
260
+		return xxx_messageInfo_Ref.Marshal(b, m, deterministic)
261
+	} else {
262
+		b = b[:cap(b)]
263
+		n, err := m.MarshalTo(b)
264
+		if err != nil {
265
+			return nil, err
266
+		}
267
+		return b[:n], nil
268
+	}
269
+}
270
+func (dst *Ref) XXX_Merge(src proto.Message) {
271
+	xxx_messageInfo_Ref.Merge(dst, src)
272
+}
273
+func (m *Ref) XXX_Size() int {
274
+	return m.Size()
275
+}
276
+func (m *Ref) XXX_DiscardUnknown() {
277
+	xxx_messageInfo_Ref.DiscardUnknown(m)
278
+}
279
+
280
+var xxx_messageInfo_Ref proto.InternalMessageInfo
281
+
282
+func (m *Ref) GetId() string {
283
+	if m != nil {
284
+		return m.Id
285
+	}
286
+	return ""
287
+}
288
+
289
+func (m *Ref) GetDef() *pb.Definition {
290
+	if m != nil {
291
+		return m.Def
292
+	}
293
+	return nil
294
+}
295
+
296
+type RefMap struct {
297
+	Refs                 map[string]*Ref `protobuf:"bytes,1,rep,name=refs,proto3" json:"refs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
298
+	XXX_NoUnkeyedLiteral struct{}        `json:"-"`
299
+	XXX_unrecognized     []byte          `json:"-"`
300
+	XXX_sizecache        int32           `json:"-"`
301
+}
302
+
201 303
 func (m *RefMap) Reset()         { *m = RefMap{} }
202 304
 func (m *RefMap) String() string { return proto.CompactTextString(m) }
203 305
 func (*RefMap) ProtoMessage()    {}
204 306
 func (*RefMap) Descriptor() ([]byte, []int) {
205
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{1}
307
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{3}
206 308
 }
207 309
 func (m *RefMap) XXX_Unmarshal(b []byte) error {
208 310
 	return m.Unmarshal(b)
... ...
@@ -231,7 +395,7 @@ func (m *RefMap) XXX_DiscardUnknown() {
231 231
 
232 232
 var xxx_messageInfo_RefMap proto.InternalMessageInfo
233 233
 
234
-func (m *RefMap) GetRefs() map[string]string {
234
+func (m *RefMap) GetRefs() map[string]*Ref {
235 235
 	if m != nil {
236 236
 		return m.Refs
237 237
 	}
... ...
@@ -250,7 +414,7 @@ func (m *ReturnRequest) Reset()         { *m = ReturnRequest{} }
250 250
 func (m *ReturnRequest) String() string { return proto.CompactTextString(m) }
251 251
 func (*ReturnRequest) ProtoMessage()    {}
252 252
 func (*ReturnRequest) Descriptor() ([]byte, []int) {
253
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{2}
253
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{4}
254 254
 }
255 255
 func (m *ReturnRequest) XXX_Unmarshal(b []byte) error {
256 256
 	return m.Unmarshal(b)
... ...
@@ -303,7 +467,7 @@ func (m *ReturnResponse) Reset()         { *m = ReturnResponse{} }
303 303
 func (m *ReturnResponse) String() string { return proto.CompactTextString(m) }
304 304
 func (*ReturnResponse) ProtoMessage()    {}
305 305
 func (*ReturnResponse) Descriptor() ([]byte, []int) {
306
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{3}
306
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{5}
307 307
 }
308 308
 func (m *ReturnResponse) XXX_Unmarshal(b []byte) error {
309 309
 	return m.Unmarshal(b)
... ...
@@ -332,6 +496,92 @@ func (m *ReturnResponse) XXX_DiscardUnknown() {
332 332
 
333 333
 var xxx_messageInfo_ReturnResponse proto.InternalMessageInfo
334 334
 
335
+type InputsRequest struct {
336
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
337
+	XXX_unrecognized     []byte   `json:"-"`
338
+	XXX_sizecache        int32    `json:"-"`
339
+}
340
+
341
+func (m *InputsRequest) Reset()         { *m = InputsRequest{} }
342
+func (m *InputsRequest) String() string { return proto.CompactTextString(m) }
343
+func (*InputsRequest) ProtoMessage()    {}
344
+func (*InputsRequest) Descriptor() ([]byte, []int) {
345
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{6}
346
+}
347
+func (m *InputsRequest) XXX_Unmarshal(b []byte) error {
348
+	return m.Unmarshal(b)
349
+}
350
+func (m *InputsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
351
+	if deterministic {
352
+		return xxx_messageInfo_InputsRequest.Marshal(b, m, deterministic)
353
+	} else {
354
+		b = b[:cap(b)]
355
+		n, err := m.MarshalTo(b)
356
+		if err != nil {
357
+			return nil, err
358
+		}
359
+		return b[:n], nil
360
+	}
361
+}
362
+func (dst *InputsRequest) XXX_Merge(src proto.Message) {
363
+	xxx_messageInfo_InputsRequest.Merge(dst, src)
364
+}
365
+func (m *InputsRequest) XXX_Size() int {
366
+	return m.Size()
367
+}
368
+func (m *InputsRequest) XXX_DiscardUnknown() {
369
+	xxx_messageInfo_InputsRequest.DiscardUnknown(m)
370
+}
371
+
372
+var xxx_messageInfo_InputsRequest proto.InternalMessageInfo
373
+
374
+type InputsResponse struct {
375
+	Definitions          map[string]*pb.Definition `protobuf:"bytes,1,rep,name=Definitions,proto3" json:"Definitions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
376
+	XXX_NoUnkeyedLiteral struct{}                  `json:"-"`
377
+	XXX_unrecognized     []byte                    `json:"-"`
378
+	XXX_sizecache        int32                     `json:"-"`
379
+}
380
+
381
+func (m *InputsResponse) Reset()         { *m = InputsResponse{} }
382
+func (m *InputsResponse) String() string { return proto.CompactTextString(m) }
383
+func (*InputsResponse) ProtoMessage()    {}
384
+func (*InputsResponse) Descriptor() ([]byte, []int) {
385
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{7}
386
+}
387
+func (m *InputsResponse) XXX_Unmarshal(b []byte) error {
388
+	return m.Unmarshal(b)
389
+}
390
+func (m *InputsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
391
+	if deterministic {
392
+		return xxx_messageInfo_InputsResponse.Marshal(b, m, deterministic)
393
+	} else {
394
+		b = b[:cap(b)]
395
+		n, err := m.MarshalTo(b)
396
+		if err != nil {
397
+			return nil, err
398
+		}
399
+		return b[:n], nil
400
+	}
401
+}
402
+func (dst *InputsResponse) XXX_Merge(src proto.Message) {
403
+	xxx_messageInfo_InputsResponse.Merge(dst, src)
404
+}
405
+func (m *InputsResponse) XXX_Size() int {
406
+	return m.Size()
407
+}
408
+func (m *InputsResponse) XXX_DiscardUnknown() {
409
+	xxx_messageInfo_InputsResponse.DiscardUnknown(m)
410
+}
411
+
412
+var xxx_messageInfo_InputsResponse proto.InternalMessageInfo
413
+
414
+func (m *InputsResponse) GetDefinitions() map[string]*pb.Definition {
415
+	if m != nil {
416
+		return m.Definitions
417
+	}
418
+	return nil
419
+}
420
+
335 421
 type ResolveImageConfigRequest struct {
336 422
 	Ref                  string       `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
337 423
 	Platform             *pb.Platform `protobuf:"bytes,2,opt,name=Platform,proto3" json:"Platform,omitempty"`
... ...
@@ -346,7 +596,7 @@ func (m *ResolveImageConfigRequest) Reset()         { *m = ResolveImageConfigReq
346 346
 func (m *ResolveImageConfigRequest) String() string { return proto.CompactTextString(m) }
347 347
 func (*ResolveImageConfigRequest) ProtoMessage()    {}
348 348
 func (*ResolveImageConfigRequest) Descriptor() ([]byte, []int) {
349
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{4}
349
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{8}
350 350
 }
351 351
 func (m *ResolveImageConfigRequest) XXX_Unmarshal(b []byte) error {
352 352
 	return m.Unmarshal(b)
... ...
@@ -415,7 +665,7 @@ func (m *ResolveImageConfigResponse) Reset()         { *m = ResolveImageConfigRe
415 415
 func (m *ResolveImageConfigResponse) String() string { return proto.CompactTextString(m) }
416 416
 func (*ResolveImageConfigResponse) ProtoMessage()    {}
417 417
 func (*ResolveImageConfigResponse) Descriptor() ([]byte, []int) {
418
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{5}
418
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{9}
419 419
 }
420 420
 func (m *ResolveImageConfigResponse) XXX_Unmarshal(b []byte) error {
421 421
 	return m.Unmarshal(b)
... ...
@@ -461,22 +711,25 @@ type SolveRequest struct {
461 461
 	// for each of the ImportCacheRefs entry to CacheImports for compatibility. (planned to be removed)
462 462
 	ImportCacheRefsDeprecated []string `protobuf:"bytes,4,rep,name=ImportCacheRefsDeprecated,proto3" json:"ImportCacheRefsDeprecated,omitempty"`
463 463
 	AllowResultReturn         bool     `protobuf:"varint,5,opt,name=allowResultReturn,proto3" json:"allowResultReturn,omitempty"`
464
+	AllowResultArrayRef       bool     `protobuf:"varint,6,opt,name=allowResultArrayRef,proto3" json:"allowResultArrayRef,omitempty"`
464 465
 	// apicaps.CapSolveInlineReturn deprecated
465 466
 	Final        bool   `protobuf:"varint,10,opt,name=Final,proto3" json:"Final,omitempty"`
466 467
 	ExporterAttr []byte `protobuf:"bytes,11,opt,name=ExporterAttr,proto3" json:"ExporterAttr,omitempty"`
467 468
 	// CacheImports was added in BuildKit v0.4.0.
468 469
 	// apicaps:CapImportCaches
469
-	CacheImports         []*CacheOptionsEntry `protobuf:"bytes,12,rep,name=CacheImports,proto3" json:"CacheImports,omitempty"`
470
-	XXX_NoUnkeyedLiteral struct{}             `json:"-"`
471
-	XXX_unrecognized     []byte               `json:"-"`
472
-	XXX_sizecache        int32                `json:"-"`
470
+	CacheImports []*CacheOptionsEntry `protobuf:"bytes,12,rep,name=CacheImports,proto3" json:"CacheImports,omitempty"`
471
+	// apicaps:CapFrontendInputs
472
+	FrontendInputs       map[string]*pb.Definition `protobuf:"bytes,13,rep,name=FrontendInputs,proto3" json:"FrontendInputs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
473
+	XXX_NoUnkeyedLiteral struct{}                  `json:"-"`
474
+	XXX_unrecognized     []byte                    `json:"-"`
475
+	XXX_sizecache        int32                     `json:"-"`
473 476
 }
474 477
 
475 478
 func (m *SolveRequest) Reset()         { *m = SolveRequest{} }
476 479
 func (m *SolveRequest) String() string { return proto.CompactTextString(m) }
477 480
 func (*SolveRequest) ProtoMessage()    {}
478 481
 func (*SolveRequest) Descriptor() ([]byte, []int) {
479
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{6}
482
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{10}
480 483
 }
481 484
 func (m *SolveRequest) XXX_Unmarshal(b []byte) error {
482 485
 	return m.Unmarshal(b)
... ...
@@ -540,6 +793,13 @@ func (m *SolveRequest) GetAllowResultReturn() bool {
540 540
 	return false
541 541
 }
542 542
 
543
+func (m *SolveRequest) GetAllowResultArrayRef() bool {
544
+	if m != nil {
545
+		return m.AllowResultArrayRef
546
+	}
547
+	return false
548
+}
549
+
543 550
 func (m *SolveRequest) GetFinal() bool {
544 551
 	if m != nil {
545 552
 		return m.Final
... ...
@@ -561,6 +821,13 @@ func (m *SolveRequest) GetCacheImports() []*CacheOptionsEntry {
561 561
 	return nil
562 562
 }
563 563
 
564
+func (m *SolveRequest) GetFrontendInputs() map[string]*pb.Definition {
565
+	if m != nil {
566
+		return m.FrontendInputs
567
+	}
568
+	return nil
569
+}
570
+
564 571
 // CacheOptionsEntry corresponds to the control.CacheOptionsEntry
565 572
 type CacheOptionsEntry struct {
566 573
 	Type                 string            `protobuf:"bytes,1,opt,name=Type,proto3" json:"Type,omitempty"`
... ...
@@ -574,7 +841,7 @@ func (m *CacheOptionsEntry) Reset()         { *m = CacheOptionsEntry{} }
574 574
 func (m *CacheOptionsEntry) String() string { return proto.CompactTextString(m) }
575 575
 func (*CacheOptionsEntry) ProtoMessage()    {}
576 576
 func (*CacheOptionsEntry) Descriptor() ([]byte, []int) {
577
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{7}
577
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{11}
578 578
 }
579 579
 func (m *CacheOptionsEntry) XXX_Unmarshal(b []byte) error {
580 580
 	return m.Unmarshal(b)
... ...
@@ -631,7 +898,7 @@ func (m *SolveResponse) Reset()         { *m = SolveResponse{} }
631 631
 func (m *SolveResponse) String() string { return proto.CompactTextString(m) }
632 632
 func (*SolveResponse) ProtoMessage()    {}
633 633
 func (*SolveResponse) Descriptor() ([]byte, []int) {
634
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{8}
634
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{12}
635 635
 }
636 636
 func (m *SolveResponse) XXX_Unmarshal(b []byte) error {
637 637
 	return m.Unmarshal(b)
... ...
@@ -687,7 +954,7 @@ func (m *ReadFileRequest) Reset()         { *m = ReadFileRequest{} }
687 687
 func (m *ReadFileRequest) String() string { return proto.CompactTextString(m) }
688 688
 func (*ReadFileRequest) ProtoMessage()    {}
689 689
 func (*ReadFileRequest) Descriptor() ([]byte, []int) {
690
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{9}
690
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{13}
691 691
 }
692 692
 func (m *ReadFileRequest) XXX_Unmarshal(b []byte) error {
693 693
 	return m.Unmarshal(b)
... ...
@@ -749,7 +1016,7 @@ func (m *FileRange) Reset()         { *m = FileRange{} }
749 749
 func (m *FileRange) String() string { return proto.CompactTextString(m) }
750 750
 func (*FileRange) ProtoMessage()    {}
751 751
 func (*FileRange) Descriptor() ([]byte, []int) {
752
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{10}
752
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{14}
753 753
 }
754 754
 func (m *FileRange) XXX_Unmarshal(b []byte) error {
755 755
 	return m.Unmarshal(b)
... ...
@@ -803,7 +1070,7 @@ func (m *ReadFileResponse) Reset()         { *m = ReadFileResponse{} }
803 803
 func (m *ReadFileResponse) String() string { return proto.CompactTextString(m) }
804 804
 func (*ReadFileResponse) ProtoMessage()    {}
805 805
 func (*ReadFileResponse) Descriptor() ([]byte, []int) {
806
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{11}
806
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{15}
807 807
 }
808 808
 func (m *ReadFileResponse) XXX_Unmarshal(b []byte) error {
809 809
 	return m.Unmarshal(b)
... ...
@@ -852,7 +1119,7 @@ func (m *ReadDirRequest) Reset()         { *m = ReadDirRequest{} }
852 852
 func (m *ReadDirRequest) String() string { return proto.CompactTextString(m) }
853 853
 func (*ReadDirRequest) ProtoMessage()    {}
854 854
 func (*ReadDirRequest) Descriptor() ([]byte, []int) {
855
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{12}
855
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{16}
856 856
 }
857 857
 func (m *ReadDirRequest) XXX_Unmarshal(b []byte) error {
858 858
 	return m.Unmarshal(b)
... ...
@@ -913,7 +1180,7 @@ func (m *ReadDirResponse) Reset()         { *m = ReadDirResponse{} }
913 913
 func (m *ReadDirResponse) String() string { return proto.CompactTextString(m) }
914 914
 func (*ReadDirResponse) ProtoMessage()    {}
915 915
 func (*ReadDirResponse) Descriptor() ([]byte, []int) {
916
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{13}
916
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{17}
917 917
 }
918 918
 func (m *ReadDirResponse) XXX_Unmarshal(b []byte) error {
919 919
 	return m.Unmarshal(b)
... ...
@@ -961,7 +1228,7 @@ func (m *StatFileRequest) Reset()         { *m = StatFileRequest{} }
961 961
 func (m *StatFileRequest) String() string { return proto.CompactTextString(m) }
962 962
 func (*StatFileRequest) ProtoMessage()    {}
963 963
 func (*StatFileRequest) Descriptor() ([]byte, []int) {
964
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{14}
964
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{18}
965 965
 }
966 966
 func (m *StatFileRequest) XXX_Unmarshal(b []byte) error {
967 967
 	return m.Unmarshal(b)
... ...
@@ -1015,7 +1282,7 @@ func (m *StatFileResponse) Reset()         { *m = StatFileResponse{} }
1015 1015
 func (m *StatFileResponse) String() string { return proto.CompactTextString(m) }
1016 1016
 func (*StatFileResponse) ProtoMessage()    {}
1017 1017
 func (*StatFileResponse) Descriptor() ([]byte, []int) {
1018
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{15}
1018
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{19}
1019 1019
 }
1020 1020
 func (m *StatFileResponse) XXX_Unmarshal(b []byte) error {
1021 1021
 	return m.Unmarshal(b)
... ...
@@ -1061,7 +1328,7 @@ func (m *PingRequest) Reset()         { *m = PingRequest{} }
1061 1061
 func (m *PingRequest) String() string { return proto.CompactTextString(m) }
1062 1062
 func (*PingRequest) ProtoMessage()    {}
1063 1063
 func (*PingRequest) Descriptor() ([]byte, []int) {
1064
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{16}
1064
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{20}
1065 1065
 }
1066 1066
 func (m *PingRequest) XXX_Unmarshal(b []byte) error {
1067 1067
 	return m.Unmarshal(b)
... ...
@@ -1103,7 +1370,7 @@ func (m *PongResponse) Reset()         { *m = PongResponse{} }
1103 1103
 func (m *PongResponse) String() string { return proto.CompactTextString(m) }
1104 1104
 func (*PongResponse) ProtoMessage()    {}
1105 1105
 func (*PongResponse) Descriptor() ([]byte, []int) {
1106
-	return fileDescriptor_gateway_eff078cadb286ceb, []int{17}
1106
+	return fileDescriptor_gateway_20a4d16709b1a720, []int{21}
1107 1107
 }
1108 1108
 func (m *PongResponse) XXX_Unmarshal(b []byte) error {
1109 1109
 	return m.Unmarshal(b)
... ...
@@ -1156,13 +1423,20 @@ func (m *PongResponse) GetWorkers() []*types1.WorkerRecord {
1156 1156
 func init() {
1157 1157
 	proto.RegisterType((*Result)(nil), "moby.buildkit.v1.frontend.Result")
1158 1158
 	proto.RegisterMapType((map[string][]byte)(nil), "moby.buildkit.v1.frontend.Result.MetadataEntry")
1159
+	proto.RegisterType((*RefMapDeprecated)(nil), "moby.buildkit.v1.frontend.RefMapDeprecated")
1160
+	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.frontend.RefMapDeprecated.RefsEntry")
1161
+	proto.RegisterType((*Ref)(nil), "moby.buildkit.v1.frontend.Ref")
1159 1162
 	proto.RegisterType((*RefMap)(nil), "moby.buildkit.v1.frontend.RefMap")
1160
-	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.frontend.RefMap.RefsEntry")
1163
+	proto.RegisterMapType((map[string]*Ref)(nil), "moby.buildkit.v1.frontend.RefMap.RefsEntry")
1161 1164
 	proto.RegisterType((*ReturnRequest)(nil), "moby.buildkit.v1.frontend.ReturnRequest")
1162 1165
 	proto.RegisterType((*ReturnResponse)(nil), "moby.buildkit.v1.frontend.ReturnResponse")
1166
+	proto.RegisterType((*InputsRequest)(nil), "moby.buildkit.v1.frontend.InputsRequest")
1167
+	proto.RegisterType((*InputsResponse)(nil), "moby.buildkit.v1.frontend.InputsResponse")
1168
+	proto.RegisterMapType((map[string]*pb.Definition)(nil), "moby.buildkit.v1.frontend.InputsResponse.DefinitionsEntry")
1163 1169
 	proto.RegisterType((*ResolveImageConfigRequest)(nil), "moby.buildkit.v1.frontend.ResolveImageConfigRequest")
1164 1170
 	proto.RegisterType((*ResolveImageConfigResponse)(nil), "moby.buildkit.v1.frontend.ResolveImageConfigResponse")
1165 1171
 	proto.RegisterType((*SolveRequest)(nil), "moby.buildkit.v1.frontend.SolveRequest")
1172
+	proto.RegisterMapType((map[string]*pb.Definition)(nil), "moby.buildkit.v1.frontend.SolveRequest.FrontendInputsEntry")
1166 1173
 	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.frontend.SolveRequest.FrontendOptEntry")
1167 1174
 	proto.RegisterType((*CacheOptionsEntry)(nil), "moby.buildkit.v1.frontend.CacheOptionsEntry")
1168 1175
 	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.frontend.CacheOptionsEntry.AttrsEntry")
... ...
@@ -1202,6 +1476,8 @@ type LLBBridgeClient interface {
1202 1202
 	StatFile(ctx context.Context, in *StatFileRequest, opts ...grpc.CallOption) (*StatFileResponse, error)
1203 1203
 	Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PongResponse, error)
1204 1204
 	Return(ctx context.Context, in *ReturnRequest, opts ...grpc.CallOption) (*ReturnResponse, error)
1205
+	// apicaps:CapFrontendInputs
1206
+	Inputs(ctx context.Context, in *InputsRequest, opts ...grpc.CallOption) (*InputsResponse, error)
1205 1207
 }
1206 1208
 
1207 1209
 type lLBBridgeClient struct {
... ...
@@ -1275,6 +1551,15 @@ func (c *lLBBridgeClient) Return(ctx context.Context, in *ReturnRequest, opts ..
1275 1275
 	return out, nil
1276 1276
 }
1277 1277
 
1278
+func (c *lLBBridgeClient) Inputs(ctx context.Context, in *InputsRequest, opts ...grpc.CallOption) (*InputsResponse, error) {
1279
+	out := new(InputsResponse)
1280
+	err := c.cc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/Inputs", in, out, opts...)
1281
+	if err != nil {
1282
+		return nil, err
1283
+	}
1284
+	return out, nil
1285
+}
1286
+
1278 1287
 // LLBBridgeServer is the server API for LLBBridge service.
1279 1288
 type LLBBridgeServer interface {
1280 1289
 	// apicaps:CapResolveImage
... ...
@@ -1289,6 +1574,8 @@ type LLBBridgeServer interface {
1289 1289
 	StatFile(context.Context, *StatFileRequest) (*StatFileResponse, error)
1290 1290
 	Ping(context.Context, *PingRequest) (*PongResponse, error)
1291 1291
 	Return(context.Context, *ReturnRequest) (*ReturnResponse, error)
1292
+	// apicaps:CapFrontendInputs
1293
+	Inputs(context.Context, *InputsRequest) (*InputsResponse, error)
1292 1294
 }
1293 1295
 
1294 1296
 func RegisterLLBBridgeServer(s *grpc.Server, srv LLBBridgeServer) {
... ...
@@ -1421,6 +1708,24 @@ func _LLBBridge_Return_Handler(srv interface{}, ctx context.Context, dec func(in
1421 1421
 	return interceptor(ctx, in, info, handler)
1422 1422
 }
1423 1423
 
1424
+func _LLBBridge_Inputs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
1425
+	in := new(InputsRequest)
1426
+	if err := dec(in); err != nil {
1427
+		return nil, err
1428
+	}
1429
+	if interceptor == nil {
1430
+		return srv.(LLBBridgeServer).Inputs(ctx, in)
1431
+	}
1432
+	info := &grpc.UnaryServerInfo{
1433
+		Server:     srv,
1434
+		FullMethod: "/moby.buildkit.v1.frontend.LLBBridge/Inputs",
1435
+	}
1436
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
1437
+		return srv.(LLBBridgeServer).Inputs(ctx, req.(*InputsRequest))
1438
+	}
1439
+	return interceptor(ctx, in, info, handler)
1440
+}
1441
+
1424 1442
 var _LLBBridge_serviceDesc = grpc.ServiceDesc{
1425 1443
 	ServiceName: "moby.buildkit.v1.frontend.LLBBridge",
1426 1444
 	HandlerType: (*LLBBridgeServer)(nil),
... ...
@@ -1453,6 +1758,10 @@ var _LLBBridge_serviceDesc = grpc.ServiceDesc{
1453 1453
 			MethodName: "Return",
1454 1454
 			Handler:    _LLBBridge_Return_Handler,
1455 1455
 		},
1456
+		{
1457
+			MethodName: "Inputs",
1458
+			Handler:    _LLBBridge_Inputs_Handler,
1459
+		},
1456 1460
 	},
1457 1461
 	Streams:  []grpc.StreamDesc{},
1458 1462
 	Metadata: "gateway.proto",
... ...
@@ -1509,29 +1818,57 @@ func (m *Result) MarshalTo(dAtA []byte) (int, error) {
1509 1509
 	return i, nil
1510 1510
 }
1511 1511
 
1512
-func (m *Result_Ref) MarshalTo(dAtA []byte) (int, error) {
1512
+func (m *Result_RefDeprecated) MarshalTo(dAtA []byte) (int, error) {
1513 1513
 	i := 0
1514 1514
 	dAtA[i] = 0xa
1515 1515
 	i++
1516
-	i = encodeVarintGateway(dAtA, i, uint64(len(m.Ref)))
1517
-	i += copy(dAtA[i:], m.Ref)
1516
+	i = encodeVarintGateway(dAtA, i, uint64(len(m.RefDeprecated)))
1517
+	i += copy(dAtA[i:], m.RefDeprecated)
1518
+	return i, nil
1519
+}
1520
+func (m *Result_RefsDeprecated) MarshalTo(dAtA []byte) (int, error) {
1521
+	i := 0
1522
+	if m.RefsDeprecated != nil {
1523
+		dAtA[i] = 0x12
1524
+		i++
1525
+		i = encodeVarintGateway(dAtA, i, uint64(m.RefsDeprecated.Size()))
1526
+		n2, err := m.RefsDeprecated.MarshalTo(dAtA[i:])
1527
+		if err != nil {
1528
+			return 0, err
1529
+		}
1530
+		i += n2
1531
+	}
1532
+	return i, nil
1533
+}
1534
+func (m *Result_Ref) MarshalTo(dAtA []byte) (int, error) {
1535
+	i := 0
1536
+	if m.Ref != nil {
1537
+		dAtA[i] = 0x1a
1538
+		i++
1539
+		i = encodeVarintGateway(dAtA, i, uint64(m.Ref.Size()))
1540
+		n3, err := m.Ref.MarshalTo(dAtA[i:])
1541
+		if err != nil {
1542
+			return 0, err
1543
+		}
1544
+		i += n3
1545
+	}
1518 1546
 	return i, nil
1519 1547
 }
1520 1548
 func (m *Result_Refs) MarshalTo(dAtA []byte) (int, error) {
1521 1549
 	i := 0
1522 1550
 	if m.Refs != nil {
1523
-		dAtA[i] = 0x12
1551
+		dAtA[i] = 0x22
1524 1552
 		i++
1525 1553
 		i = encodeVarintGateway(dAtA, i, uint64(m.Refs.Size()))
1526
-		n2, err := m.Refs.MarshalTo(dAtA[i:])
1554
+		n4, err := m.Refs.MarshalTo(dAtA[i:])
1527 1555
 		if err != nil {
1528 1556
 			return 0, err
1529 1557
 		}
1530
-		i += n2
1558
+		i += n4
1531 1559
 	}
1532 1560
 	return i, nil
1533 1561
 }
1534
-func (m *RefMap) Marshal() (dAtA []byte, err error) {
1562
+func (m *RefMapDeprecated) Marshal() (dAtA []byte, err error) {
1535 1563
 	size := m.Size()
1536 1564
 	dAtA = make([]byte, size)
1537 1565
 	n, err := m.MarshalTo(dAtA)
... ...
@@ -1541,7 +1878,7 @@ func (m *RefMap) Marshal() (dAtA []byte, err error) {
1541 1541
 	return dAtA[:n], nil
1542 1542
 }
1543 1543
 
1544
-func (m *RefMap) MarshalTo(dAtA []byte) (int, error) {
1544
+func (m *RefMapDeprecated) MarshalTo(dAtA []byte) (int, error) {
1545 1545
 	var i int
1546 1546
 	_ = i
1547 1547
 	var l int
... ...
@@ -1569,6 +1906,92 @@ func (m *RefMap) MarshalTo(dAtA []byte) (int, error) {
1569 1569
 	return i, nil
1570 1570
 }
1571 1571
 
1572
+func (m *Ref) Marshal() (dAtA []byte, err error) {
1573
+	size := m.Size()
1574
+	dAtA = make([]byte, size)
1575
+	n, err := m.MarshalTo(dAtA)
1576
+	if err != nil {
1577
+		return nil, err
1578
+	}
1579
+	return dAtA[:n], nil
1580
+}
1581
+
1582
+func (m *Ref) MarshalTo(dAtA []byte) (int, error) {
1583
+	var i int
1584
+	_ = i
1585
+	var l int
1586
+	_ = l
1587
+	if len(m.Id) > 0 {
1588
+		dAtA[i] = 0xa
1589
+		i++
1590
+		i = encodeVarintGateway(dAtA, i, uint64(len(m.Id)))
1591
+		i += copy(dAtA[i:], m.Id)
1592
+	}
1593
+	if m.Def != nil {
1594
+		dAtA[i] = 0x12
1595
+		i++
1596
+		i = encodeVarintGateway(dAtA, i, uint64(m.Def.Size()))
1597
+		n5, err := m.Def.MarshalTo(dAtA[i:])
1598
+		if err != nil {
1599
+			return 0, err
1600
+		}
1601
+		i += n5
1602
+	}
1603
+	if m.XXX_unrecognized != nil {
1604
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1605
+	}
1606
+	return i, nil
1607
+}
1608
+
1609
+func (m *RefMap) Marshal() (dAtA []byte, err error) {
1610
+	size := m.Size()
1611
+	dAtA = make([]byte, size)
1612
+	n, err := m.MarshalTo(dAtA)
1613
+	if err != nil {
1614
+		return nil, err
1615
+	}
1616
+	return dAtA[:n], nil
1617
+}
1618
+
1619
+func (m *RefMap) MarshalTo(dAtA []byte) (int, error) {
1620
+	var i int
1621
+	_ = i
1622
+	var l int
1623
+	_ = l
1624
+	if len(m.Refs) > 0 {
1625
+		for k, _ := range m.Refs {
1626
+			dAtA[i] = 0xa
1627
+			i++
1628
+			v := m.Refs[k]
1629
+			msgSize := 0
1630
+			if v != nil {
1631
+				msgSize = v.Size()
1632
+				msgSize += 1 + sovGateway(uint64(msgSize))
1633
+			}
1634
+			mapSize := 1 + len(k) + sovGateway(uint64(len(k))) + msgSize
1635
+			i = encodeVarintGateway(dAtA, i, uint64(mapSize))
1636
+			dAtA[i] = 0xa
1637
+			i++
1638
+			i = encodeVarintGateway(dAtA, i, uint64(len(k)))
1639
+			i += copy(dAtA[i:], k)
1640
+			if v != nil {
1641
+				dAtA[i] = 0x12
1642
+				i++
1643
+				i = encodeVarintGateway(dAtA, i, uint64(v.Size()))
1644
+				n6, err := v.MarshalTo(dAtA[i:])
1645
+				if err != nil {
1646
+					return 0, err
1647
+				}
1648
+				i += n6
1649
+			}
1650
+		}
1651
+	}
1652
+	if m.XXX_unrecognized != nil {
1653
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1654
+	}
1655
+	return i, nil
1656
+}
1657
+
1572 1658
 func (m *ReturnRequest) Marshal() (dAtA []byte, err error) {
1573 1659
 	size := m.Size()
1574 1660
 	dAtA = make([]byte, size)
... ...
@@ -1588,21 +2011,21 @@ func (m *ReturnRequest) MarshalTo(dAtA []byte) (int, error) {
1588 1588
 		dAtA[i] = 0xa
1589 1589
 		i++
1590 1590
 		i = encodeVarintGateway(dAtA, i, uint64(m.Result.Size()))
1591
-		n3, err := m.Result.MarshalTo(dAtA[i:])
1591
+		n7, err := m.Result.MarshalTo(dAtA[i:])
1592 1592
 		if err != nil {
1593 1593
 			return 0, err
1594 1594
 		}
1595
-		i += n3
1595
+		i += n7
1596 1596
 	}
1597 1597
 	if m.Error != nil {
1598 1598
 		dAtA[i] = 0x12
1599 1599
 		i++
1600 1600
 		i = encodeVarintGateway(dAtA, i, uint64(m.Error.Size()))
1601
-		n4, err := m.Error.MarshalTo(dAtA[i:])
1601
+		n8, err := m.Error.MarshalTo(dAtA[i:])
1602 1602
 		if err != nil {
1603 1603
 			return 0, err
1604 1604
 		}
1605
-		i += n4
1605
+		i += n8
1606 1606
 	}
1607 1607
 	if m.XXX_unrecognized != nil {
1608 1608
 		i += copy(dAtA[i:], m.XXX_unrecognized)
... ...
@@ -1631,6 +2054,76 @@ func (m *ReturnResponse) MarshalTo(dAtA []byte) (int, error) {
1631 1631
 	return i, nil
1632 1632
 }
1633 1633
 
1634
+func (m *InputsRequest) Marshal() (dAtA []byte, err error) {
1635
+	size := m.Size()
1636
+	dAtA = make([]byte, size)
1637
+	n, err := m.MarshalTo(dAtA)
1638
+	if err != nil {
1639
+		return nil, err
1640
+	}
1641
+	return dAtA[:n], nil
1642
+}
1643
+
1644
+func (m *InputsRequest) MarshalTo(dAtA []byte) (int, error) {
1645
+	var i int
1646
+	_ = i
1647
+	var l int
1648
+	_ = l
1649
+	if m.XXX_unrecognized != nil {
1650
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1651
+	}
1652
+	return i, nil
1653
+}
1654
+
1655
+func (m *InputsResponse) Marshal() (dAtA []byte, err error) {
1656
+	size := m.Size()
1657
+	dAtA = make([]byte, size)
1658
+	n, err := m.MarshalTo(dAtA)
1659
+	if err != nil {
1660
+		return nil, err
1661
+	}
1662
+	return dAtA[:n], nil
1663
+}
1664
+
1665
+func (m *InputsResponse) MarshalTo(dAtA []byte) (int, error) {
1666
+	var i int
1667
+	_ = i
1668
+	var l int
1669
+	_ = l
1670
+	if len(m.Definitions) > 0 {
1671
+		for k, _ := range m.Definitions {
1672
+			dAtA[i] = 0xa
1673
+			i++
1674
+			v := m.Definitions[k]
1675
+			msgSize := 0
1676
+			if v != nil {
1677
+				msgSize = v.Size()
1678
+				msgSize += 1 + sovGateway(uint64(msgSize))
1679
+			}
1680
+			mapSize := 1 + len(k) + sovGateway(uint64(len(k))) + msgSize
1681
+			i = encodeVarintGateway(dAtA, i, uint64(mapSize))
1682
+			dAtA[i] = 0xa
1683
+			i++
1684
+			i = encodeVarintGateway(dAtA, i, uint64(len(k)))
1685
+			i += copy(dAtA[i:], k)
1686
+			if v != nil {
1687
+				dAtA[i] = 0x12
1688
+				i++
1689
+				i = encodeVarintGateway(dAtA, i, uint64(v.Size()))
1690
+				n9, err := v.MarshalTo(dAtA[i:])
1691
+				if err != nil {
1692
+					return 0, err
1693
+				}
1694
+				i += n9
1695
+			}
1696
+		}
1697
+	}
1698
+	if m.XXX_unrecognized != nil {
1699
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1700
+	}
1701
+	return i, nil
1702
+}
1703
+
1634 1704
 func (m *ResolveImageConfigRequest) Marshal() (dAtA []byte, err error) {
1635 1705
 	size := m.Size()
1636 1706
 	dAtA = make([]byte, size)
... ...
@@ -1656,11 +2149,11 @@ func (m *ResolveImageConfigRequest) MarshalTo(dAtA []byte) (int, error) {
1656 1656
 		dAtA[i] = 0x12
1657 1657
 		i++
1658 1658
 		i = encodeVarintGateway(dAtA, i, uint64(m.Platform.Size()))
1659
-		n5, err := m.Platform.MarshalTo(dAtA[i:])
1659
+		n10, err := m.Platform.MarshalTo(dAtA[i:])
1660 1660
 		if err != nil {
1661 1661
 			return 0, err
1662 1662
 		}
1663
-		i += n5
1663
+		i += n10
1664 1664
 	}
1665 1665
 	if len(m.ResolveMode) > 0 {
1666 1666
 		dAtA[i] = 0x1a
... ...
@@ -1732,11 +2225,11 @@ func (m *SolveRequest) MarshalTo(dAtA []byte) (int, error) {
1732 1732
 		dAtA[i] = 0xa
1733 1733
 		i++
1734 1734
 		i = encodeVarintGateway(dAtA, i, uint64(m.Definition.Size()))
1735
-		n6, err := m.Definition.MarshalTo(dAtA[i:])
1735
+		n11, err := m.Definition.MarshalTo(dAtA[i:])
1736 1736
 		if err != nil {
1737 1737
 			return 0, err
1738 1738
 		}
1739
-		i += n6
1739
+		i += n11
1740 1740
 	}
1741 1741
 	if len(m.Frontend) > 0 {
1742 1742
 		dAtA[i] = 0x12
... ...
@@ -1786,6 +2279,16 @@ func (m *SolveRequest) MarshalTo(dAtA []byte) (int, error) {
1786 1786
 		}
1787 1787
 		i++
1788 1788
 	}
1789
+	if m.AllowResultArrayRef {
1790
+		dAtA[i] = 0x30
1791
+		i++
1792
+		if m.AllowResultArrayRef {
1793
+			dAtA[i] = 1
1794
+		} else {
1795
+			dAtA[i] = 0
1796
+		}
1797
+		i++
1798
+	}
1789 1799
 	if m.Final {
1790 1800
 		dAtA[i] = 0x50
1791 1801
 		i++
... ...
@@ -1814,6 +2317,34 @@ func (m *SolveRequest) MarshalTo(dAtA []byte) (int, error) {
1814 1814
 			i += n
1815 1815
 		}
1816 1816
 	}
1817
+	if len(m.FrontendInputs) > 0 {
1818
+		for k, _ := range m.FrontendInputs {
1819
+			dAtA[i] = 0x6a
1820
+			i++
1821
+			v := m.FrontendInputs[k]
1822
+			msgSize := 0
1823
+			if v != nil {
1824
+				msgSize = v.Size()
1825
+				msgSize += 1 + sovGateway(uint64(msgSize))
1826
+			}
1827
+			mapSize := 1 + len(k) + sovGateway(uint64(len(k))) + msgSize
1828
+			i = encodeVarintGateway(dAtA, i, uint64(mapSize))
1829
+			dAtA[i] = 0xa
1830
+			i++
1831
+			i = encodeVarintGateway(dAtA, i, uint64(len(k)))
1832
+			i += copy(dAtA[i:], k)
1833
+			if v != nil {
1834
+				dAtA[i] = 0x12
1835
+				i++
1836
+				i = encodeVarintGateway(dAtA, i, uint64(v.Size()))
1837
+				n12, err := v.MarshalTo(dAtA[i:])
1838
+				if err != nil {
1839
+					return 0, err
1840
+				}
1841
+				i += n12
1842
+			}
1843
+		}
1844
+	}
1817 1845
 	if m.XXX_unrecognized != nil {
1818 1846
 		i += copy(dAtA[i:], m.XXX_unrecognized)
1819 1847
 	}
... ...
@@ -1889,11 +2420,11 @@ func (m *SolveResponse) MarshalTo(dAtA []byte) (int, error) {
1889 1889
 		dAtA[i] = 0x1a
1890 1890
 		i++
1891 1891
 		i = encodeVarintGateway(dAtA, i, uint64(m.Result.Size()))
1892
-		n7, err := m.Result.MarshalTo(dAtA[i:])
1892
+		n13, err := m.Result.MarshalTo(dAtA[i:])
1893 1893
 		if err != nil {
1894 1894
 			return 0, err
1895 1895
 		}
1896
-		i += n7
1896
+		i += n13
1897 1897
 	}
1898 1898
 	if m.XXX_unrecognized != nil {
1899 1899
 		i += copy(dAtA[i:], m.XXX_unrecognized)
... ...
@@ -1932,11 +2463,11 @@ func (m *ReadFileRequest) MarshalTo(dAtA []byte) (int, error) {
1932 1932
 		dAtA[i] = 0x1a
1933 1933
 		i++
1934 1934
 		i = encodeVarintGateway(dAtA, i, uint64(m.Range.Size()))
1935
-		n8, err := m.Range.MarshalTo(dAtA[i:])
1935
+		n14, err := m.Range.MarshalTo(dAtA[i:])
1936 1936
 		if err != nil {
1937 1937
 			return 0, err
1938 1938
 		}
1939
-		i += n8
1939
+		i += n14
1940 1940
 	}
1941 1941
 	if m.XXX_unrecognized != nil {
1942 1942
 		i += copy(dAtA[i:], m.XXX_unrecognized)
... ...
@@ -2126,11 +2657,11 @@ func (m *StatFileResponse) MarshalTo(dAtA []byte) (int, error) {
2126 2126
 		dAtA[i] = 0xa
2127 2127
 		i++
2128 2128
 		i = encodeVarintGateway(dAtA, i, uint64(m.Stat.Size()))
2129
-		n9, err := m.Stat.MarshalTo(dAtA[i:])
2129
+		n15, err := m.Stat.MarshalTo(dAtA[i:])
2130 2130
 		if err != nil {
2131 2131
 			return 0, err
2132 2132
 		}
2133
-		i += n9
2133
+		i += n15
2134 2134
 	}
2135 2135
 	if m.XXX_unrecognized != nil {
2136 2136
 		i += copy(dAtA[i:], m.XXX_unrecognized)
... ...
@@ -2252,16 +2783,40 @@ func (m *Result) Size() (n int) {
2252 2252
 	return n
2253 2253
 }
2254 2254
 
2255
-func (m *Result_Ref) Size() (n int) {
2255
+func (m *Result_RefDeprecated) Size() (n int) {
2256 2256
 	if m == nil {
2257 2257
 		return 0
2258 2258
 	}
2259 2259
 	var l int
2260 2260
 	_ = l
2261
-	l = len(m.Ref)
2261
+	l = len(m.RefDeprecated)
2262 2262
 	n += 1 + l + sovGateway(uint64(l))
2263 2263
 	return n
2264 2264
 }
2265
+func (m *Result_RefsDeprecated) Size() (n int) {
2266
+	if m == nil {
2267
+		return 0
2268
+	}
2269
+	var l int
2270
+	_ = l
2271
+	if m.RefsDeprecated != nil {
2272
+		l = m.RefsDeprecated.Size()
2273
+		n += 1 + l + sovGateway(uint64(l))
2274
+	}
2275
+	return n
2276
+}
2277
+func (m *Result_Ref) Size() (n int) {
2278
+	if m == nil {
2279
+		return 0
2280
+	}
2281
+	var l int
2282
+	_ = l
2283
+	if m.Ref != nil {
2284
+		l = m.Ref.Size()
2285
+		n += 1 + l + sovGateway(uint64(l))
2286
+	}
2287
+	return n
2288
+}
2265 2289
 func (m *Result_Refs) Size() (n int) {
2266 2290
 	if m == nil {
2267 2291
 		return 0
... ...
@@ -2274,7 +2829,7 @@ func (m *Result_Refs) Size() (n int) {
2274 2274
 	}
2275 2275
 	return n
2276 2276
 }
2277
-func (m *RefMap) Size() (n int) {
2277
+func (m *RefMapDeprecated) Size() (n int) {
2278 2278
 	if m == nil {
2279 2279
 		return 0
2280 2280
 	}
... ...
@@ -2294,6 +2849,51 @@ func (m *RefMap) Size() (n int) {
2294 2294
 	return n
2295 2295
 }
2296 2296
 
2297
+func (m *Ref) Size() (n int) {
2298
+	if m == nil {
2299
+		return 0
2300
+	}
2301
+	var l int
2302
+	_ = l
2303
+	l = len(m.Id)
2304
+	if l > 0 {
2305
+		n += 1 + l + sovGateway(uint64(l))
2306
+	}
2307
+	if m.Def != nil {
2308
+		l = m.Def.Size()
2309
+		n += 1 + l + sovGateway(uint64(l))
2310
+	}
2311
+	if m.XXX_unrecognized != nil {
2312
+		n += len(m.XXX_unrecognized)
2313
+	}
2314
+	return n
2315
+}
2316
+
2317
+func (m *RefMap) Size() (n int) {
2318
+	if m == nil {
2319
+		return 0
2320
+	}
2321
+	var l int
2322
+	_ = l
2323
+	if len(m.Refs) > 0 {
2324
+		for k, v := range m.Refs {
2325
+			_ = k
2326
+			_ = v
2327
+			l = 0
2328
+			if v != nil {
2329
+				l = v.Size()
2330
+				l += 1 + sovGateway(uint64(l))
2331
+			}
2332
+			mapEntrySize := 1 + len(k) + sovGateway(uint64(len(k))) + l
2333
+			n += mapEntrySize + 1 + sovGateway(uint64(mapEntrySize))
2334
+		}
2335
+	}
2336
+	if m.XXX_unrecognized != nil {
2337
+		n += len(m.XXX_unrecognized)
2338
+	}
2339
+	return n
2340
+}
2341
+
2297 2342
 func (m *ReturnRequest) Size() (n int) {
2298 2343
 	if m == nil {
2299 2344
 		return 0
... ...
@@ -2326,6 +2926,43 @@ func (m *ReturnResponse) Size() (n int) {
2326 2326
 	return n
2327 2327
 }
2328 2328
 
2329
+func (m *InputsRequest) Size() (n int) {
2330
+	if m == nil {
2331
+		return 0
2332
+	}
2333
+	var l int
2334
+	_ = l
2335
+	if m.XXX_unrecognized != nil {
2336
+		n += len(m.XXX_unrecognized)
2337
+	}
2338
+	return n
2339
+}
2340
+
2341
+func (m *InputsResponse) Size() (n int) {
2342
+	if m == nil {
2343
+		return 0
2344
+	}
2345
+	var l int
2346
+	_ = l
2347
+	if len(m.Definitions) > 0 {
2348
+		for k, v := range m.Definitions {
2349
+			_ = k
2350
+			_ = v
2351
+			l = 0
2352
+			if v != nil {
2353
+				l = v.Size()
2354
+				l += 1 + sovGateway(uint64(l))
2355
+			}
2356
+			mapEntrySize := 1 + len(k) + sovGateway(uint64(len(k))) + l
2357
+			n += mapEntrySize + 1 + sovGateway(uint64(mapEntrySize))
2358
+		}
2359
+	}
2360
+	if m.XXX_unrecognized != nil {
2361
+		n += len(m.XXX_unrecognized)
2362
+	}
2363
+	return n
2364
+}
2365
+
2329 2366
 func (m *ResolveImageConfigRequest) Size() (n int) {
2330 2367
 	if m == nil {
2331 2368
 		return 0
... ...
@@ -2405,6 +3042,9 @@ func (m *SolveRequest) Size() (n int) {
2405 2405
 	if m.AllowResultReturn {
2406 2406
 		n += 2
2407 2407
 	}
2408
+	if m.AllowResultArrayRef {
2409
+		n += 2
2410
+	}
2408 2411
 	if m.Final {
2409 2412
 		n += 2
2410 2413
 	}
... ...
@@ -2418,6 +3058,19 @@ func (m *SolveRequest) Size() (n int) {
2418 2418
 			n += 1 + l + sovGateway(uint64(l))
2419 2419
 		}
2420 2420
 	}
2421
+	if len(m.FrontendInputs) > 0 {
2422
+		for k, v := range m.FrontendInputs {
2423
+			_ = k
2424
+			_ = v
2425
+			l = 0
2426
+			if v != nil {
2427
+				l = v.Size()
2428
+				l += 1 + sovGateway(uint64(l))
2429
+			}
2430
+			mapEntrySize := 1 + len(k) + sovGateway(uint64(len(k))) + l
2431
+			n += mapEntrySize + 1 + sovGateway(uint64(mapEntrySize))
2432
+		}
2433
+	}
2421 2434
 	if m.XXX_unrecognized != nil {
2422 2435
 		n += len(m.XXX_unrecognized)
2423 2436
 	}
... ...
@@ -2690,7 +3343,7 @@ func (m *Result) Unmarshal(dAtA []byte) error {
2690 2690
 		switch fieldNum {
2691 2691
 		case 1:
2692 2692
 			if wireType != 2 {
2693
-				return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType)
2693
+				return fmt.Errorf("proto: wrong wireType = %d for field RefDeprecated", wireType)
2694 2694
 			}
2695 2695
 			var stringLen uint64
2696 2696
 			for shift := uint(0); ; shift += 7 {
... ...
@@ -2715,10 +3368,74 @@ func (m *Result) Unmarshal(dAtA []byte) error {
2715 2715
 			if postIndex > l {
2716 2716
 				return io.ErrUnexpectedEOF
2717 2717
 			}
2718
-			m.Result = &Result_Ref{string(dAtA[iNdEx:postIndex])}
2718
+			m.Result = &Result_RefDeprecated{string(dAtA[iNdEx:postIndex])}
2719 2719
 			iNdEx = postIndex
2720 2720
 		case 2:
2721 2721
 			if wireType != 2 {
2722
+				return fmt.Errorf("proto: wrong wireType = %d for field RefsDeprecated", wireType)
2723
+			}
2724
+			var msglen int
2725
+			for shift := uint(0); ; shift += 7 {
2726
+				if shift >= 64 {
2727
+					return ErrIntOverflowGateway
2728
+				}
2729
+				if iNdEx >= l {
2730
+					return io.ErrUnexpectedEOF
2731
+				}
2732
+				b := dAtA[iNdEx]
2733
+				iNdEx++
2734
+				msglen |= (int(b) & 0x7F) << shift
2735
+				if b < 0x80 {
2736
+					break
2737
+				}
2738
+			}
2739
+			if msglen < 0 {
2740
+				return ErrInvalidLengthGateway
2741
+			}
2742
+			postIndex := iNdEx + msglen
2743
+			if postIndex > l {
2744
+				return io.ErrUnexpectedEOF
2745
+			}
2746
+			v := &RefMapDeprecated{}
2747
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
2748
+				return err
2749
+			}
2750
+			m.Result = &Result_RefsDeprecated{v}
2751
+			iNdEx = postIndex
2752
+		case 3:
2753
+			if wireType != 2 {
2754
+				return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType)
2755
+			}
2756
+			var msglen int
2757
+			for shift := uint(0); ; shift += 7 {
2758
+				if shift >= 64 {
2759
+					return ErrIntOverflowGateway
2760
+				}
2761
+				if iNdEx >= l {
2762
+					return io.ErrUnexpectedEOF
2763
+				}
2764
+				b := dAtA[iNdEx]
2765
+				iNdEx++
2766
+				msglen |= (int(b) & 0x7F) << shift
2767
+				if b < 0x80 {
2768
+					break
2769
+				}
2770
+			}
2771
+			if msglen < 0 {
2772
+				return ErrInvalidLengthGateway
2773
+			}
2774
+			postIndex := iNdEx + msglen
2775
+			if postIndex > l {
2776
+				return io.ErrUnexpectedEOF
2777
+			}
2778
+			v := &Ref{}
2779
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
2780
+				return err
2781
+			}
2782
+			m.Result = &Result_Ref{v}
2783
+			iNdEx = postIndex
2784
+		case 4:
2785
+			if wireType != 2 {
2722 2786
 				return fmt.Errorf("proto: wrong wireType = %d for field Refs", wireType)
2723 2787
 			}
2724 2788
 			var msglen int
... ...
@@ -2890,7 +3607,7 @@ func (m *Result) Unmarshal(dAtA []byte) error {
2890 2890
 	}
2891 2891
 	return nil
2892 2892
 }
2893
-func (m *RefMap) Unmarshal(dAtA []byte) error {
2893
+func (m *RefMapDeprecated) Unmarshal(dAtA []byte) error {
2894 2894
 	l := len(dAtA)
2895 2895
 	iNdEx := 0
2896 2896
 	for iNdEx < l {
... ...
@@ -2913,10 +3630,10 @@ func (m *RefMap) Unmarshal(dAtA []byte) error {
2913 2913
 		fieldNum := int32(wire >> 3)
2914 2914
 		wireType := int(wire & 0x7)
2915 2915
 		if wireType == 4 {
2916
-			return fmt.Errorf("proto: RefMap: wiretype end group for non-group")
2916
+			return fmt.Errorf("proto: RefMapDeprecated: wiretype end group for non-group")
2917 2917
 		}
2918 2918
 		if fieldNum <= 0 {
2919
-			return fmt.Errorf("proto: RefMap: illegal tag %d (wire type %d)", fieldNum, wire)
2919
+			return fmt.Errorf("proto: RefMapDeprecated: illegal tag %d (wire type %d)", fieldNum, wire)
2920 2920
 		}
2921 2921
 		switch fieldNum {
2922 2922
 		case 1:
... ...
@@ -3059,6 +3776,293 @@ func (m *RefMap) Unmarshal(dAtA []byte) error {
3059 3059
 	}
3060 3060
 	return nil
3061 3061
 }
3062
+func (m *Ref) Unmarshal(dAtA []byte) error {
3063
+	l := len(dAtA)
3064
+	iNdEx := 0
3065
+	for iNdEx < l {
3066
+		preIndex := iNdEx
3067
+		var wire uint64
3068
+		for shift := uint(0); ; shift += 7 {
3069
+			if shift >= 64 {
3070
+				return ErrIntOverflowGateway
3071
+			}
3072
+			if iNdEx >= l {
3073
+				return io.ErrUnexpectedEOF
3074
+			}
3075
+			b := dAtA[iNdEx]
3076
+			iNdEx++
3077
+			wire |= (uint64(b) & 0x7F) << shift
3078
+			if b < 0x80 {
3079
+				break
3080
+			}
3081
+		}
3082
+		fieldNum := int32(wire >> 3)
3083
+		wireType := int(wire & 0x7)
3084
+		if wireType == 4 {
3085
+			return fmt.Errorf("proto: Ref: wiretype end group for non-group")
3086
+		}
3087
+		if fieldNum <= 0 {
3088
+			return fmt.Errorf("proto: Ref: illegal tag %d (wire type %d)", fieldNum, wire)
3089
+		}
3090
+		switch fieldNum {
3091
+		case 1:
3092
+			if wireType != 2 {
3093
+				return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType)
3094
+			}
3095
+			var stringLen uint64
3096
+			for shift := uint(0); ; shift += 7 {
3097
+				if shift >= 64 {
3098
+					return ErrIntOverflowGateway
3099
+				}
3100
+				if iNdEx >= l {
3101
+					return io.ErrUnexpectedEOF
3102
+				}
3103
+				b := dAtA[iNdEx]
3104
+				iNdEx++
3105
+				stringLen |= (uint64(b) & 0x7F) << shift
3106
+				if b < 0x80 {
3107
+					break
3108
+				}
3109
+			}
3110
+			intStringLen := int(stringLen)
3111
+			if intStringLen < 0 {
3112
+				return ErrInvalidLengthGateway
3113
+			}
3114
+			postIndex := iNdEx + intStringLen
3115
+			if postIndex > l {
3116
+				return io.ErrUnexpectedEOF
3117
+			}
3118
+			m.Id = string(dAtA[iNdEx:postIndex])
3119
+			iNdEx = postIndex
3120
+		case 2:
3121
+			if wireType != 2 {
3122
+				return fmt.Errorf("proto: wrong wireType = %d for field Def", wireType)
3123
+			}
3124
+			var msglen int
3125
+			for shift := uint(0); ; shift += 7 {
3126
+				if shift >= 64 {
3127
+					return ErrIntOverflowGateway
3128
+				}
3129
+				if iNdEx >= l {
3130
+					return io.ErrUnexpectedEOF
3131
+				}
3132
+				b := dAtA[iNdEx]
3133
+				iNdEx++
3134
+				msglen |= (int(b) & 0x7F) << shift
3135
+				if b < 0x80 {
3136
+					break
3137
+				}
3138
+			}
3139
+			if msglen < 0 {
3140
+				return ErrInvalidLengthGateway
3141
+			}
3142
+			postIndex := iNdEx + msglen
3143
+			if postIndex > l {
3144
+				return io.ErrUnexpectedEOF
3145
+			}
3146
+			if m.Def == nil {
3147
+				m.Def = &pb.Definition{}
3148
+			}
3149
+			if err := m.Def.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
3150
+				return err
3151
+			}
3152
+			iNdEx = postIndex
3153
+		default:
3154
+			iNdEx = preIndex
3155
+			skippy, err := skipGateway(dAtA[iNdEx:])
3156
+			if err != nil {
3157
+				return err
3158
+			}
3159
+			if skippy < 0 {
3160
+				return ErrInvalidLengthGateway
3161
+			}
3162
+			if (iNdEx + skippy) > l {
3163
+				return io.ErrUnexpectedEOF
3164
+			}
3165
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3166
+			iNdEx += skippy
3167
+		}
3168
+	}
3169
+
3170
+	if iNdEx > l {
3171
+		return io.ErrUnexpectedEOF
3172
+	}
3173
+	return nil
3174
+}
3175
+func (m *RefMap) Unmarshal(dAtA []byte) error {
3176
+	l := len(dAtA)
3177
+	iNdEx := 0
3178
+	for iNdEx < l {
3179
+		preIndex := iNdEx
3180
+		var wire uint64
3181
+		for shift := uint(0); ; shift += 7 {
3182
+			if shift >= 64 {
3183
+				return ErrIntOverflowGateway
3184
+			}
3185
+			if iNdEx >= l {
3186
+				return io.ErrUnexpectedEOF
3187
+			}
3188
+			b := dAtA[iNdEx]
3189
+			iNdEx++
3190
+			wire |= (uint64(b) & 0x7F) << shift
3191
+			if b < 0x80 {
3192
+				break
3193
+			}
3194
+		}
3195
+		fieldNum := int32(wire >> 3)
3196
+		wireType := int(wire & 0x7)
3197
+		if wireType == 4 {
3198
+			return fmt.Errorf("proto: RefMap: wiretype end group for non-group")
3199
+		}
3200
+		if fieldNum <= 0 {
3201
+			return fmt.Errorf("proto: RefMap: illegal tag %d (wire type %d)", fieldNum, wire)
3202
+		}
3203
+		switch fieldNum {
3204
+		case 1:
3205
+			if wireType != 2 {
3206
+				return fmt.Errorf("proto: wrong wireType = %d for field Refs", wireType)
3207
+			}
3208
+			var msglen int
3209
+			for shift := uint(0); ; shift += 7 {
3210
+				if shift >= 64 {
3211
+					return ErrIntOverflowGateway
3212
+				}
3213
+				if iNdEx >= l {
3214
+					return io.ErrUnexpectedEOF
3215
+				}
3216
+				b := dAtA[iNdEx]
3217
+				iNdEx++
3218
+				msglen |= (int(b) & 0x7F) << shift
3219
+				if b < 0x80 {
3220
+					break
3221
+				}
3222
+			}
3223
+			if msglen < 0 {
3224
+				return ErrInvalidLengthGateway
3225
+			}
3226
+			postIndex := iNdEx + msglen
3227
+			if postIndex > l {
3228
+				return io.ErrUnexpectedEOF
3229
+			}
3230
+			if m.Refs == nil {
3231
+				m.Refs = make(map[string]*Ref)
3232
+			}
3233
+			var mapkey string
3234
+			var mapvalue *Ref
3235
+			for iNdEx < postIndex {
3236
+				entryPreIndex := iNdEx
3237
+				var wire uint64
3238
+				for shift := uint(0); ; shift += 7 {
3239
+					if shift >= 64 {
3240
+						return ErrIntOverflowGateway
3241
+					}
3242
+					if iNdEx >= l {
3243
+						return io.ErrUnexpectedEOF
3244
+					}
3245
+					b := dAtA[iNdEx]
3246
+					iNdEx++
3247
+					wire |= (uint64(b) & 0x7F) << shift
3248
+					if b < 0x80 {
3249
+						break
3250
+					}
3251
+				}
3252
+				fieldNum := int32(wire >> 3)
3253
+				if fieldNum == 1 {
3254
+					var stringLenmapkey uint64
3255
+					for shift := uint(0); ; shift += 7 {
3256
+						if shift >= 64 {
3257
+							return ErrIntOverflowGateway
3258
+						}
3259
+						if iNdEx >= l {
3260
+							return io.ErrUnexpectedEOF
3261
+						}
3262
+						b := dAtA[iNdEx]
3263
+						iNdEx++
3264
+						stringLenmapkey |= (uint64(b) & 0x7F) << shift
3265
+						if b < 0x80 {
3266
+							break
3267
+						}
3268
+					}
3269
+					intStringLenmapkey := int(stringLenmapkey)
3270
+					if intStringLenmapkey < 0 {
3271
+						return ErrInvalidLengthGateway
3272
+					}
3273
+					postStringIndexmapkey := iNdEx + intStringLenmapkey
3274
+					if postStringIndexmapkey > l {
3275
+						return io.ErrUnexpectedEOF
3276
+					}
3277
+					mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
3278
+					iNdEx = postStringIndexmapkey
3279
+				} else if fieldNum == 2 {
3280
+					var mapmsglen int
3281
+					for shift := uint(0); ; shift += 7 {
3282
+						if shift >= 64 {
3283
+							return ErrIntOverflowGateway
3284
+						}
3285
+						if iNdEx >= l {
3286
+							return io.ErrUnexpectedEOF
3287
+						}
3288
+						b := dAtA[iNdEx]
3289
+						iNdEx++
3290
+						mapmsglen |= (int(b) & 0x7F) << shift
3291
+						if b < 0x80 {
3292
+							break
3293
+						}
3294
+					}
3295
+					if mapmsglen < 0 {
3296
+						return ErrInvalidLengthGateway
3297
+					}
3298
+					postmsgIndex := iNdEx + mapmsglen
3299
+					if mapmsglen < 0 {
3300
+						return ErrInvalidLengthGateway
3301
+					}
3302
+					if postmsgIndex > l {
3303
+						return io.ErrUnexpectedEOF
3304
+					}
3305
+					mapvalue = &Ref{}
3306
+					if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil {
3307
+						return err
3308
+					}
3309
+					iNdEx = postmsgIndex
3310
+				} else {
3311
+					iNdEx = entryPreIndex
3312
+					skippy, err := skipGateway(dAtA[iNdEx:])
3313
+					if err != nil {
3314
+						return err
3315
+					}
3316
+					if skippy < 0 {
3317
+						return ErrInvalidLengthGateway
3318
+					}
3319
+					if (iNdEx + skippy) > postIndex {
3320
+						return io.ErrUnexpectedEOF
3321
+					}
3322
+					iNdEx += skippy
3323
+				}
3324
+			}
3325
+			m.Refs[mapkey] = mapvalue
3326
+			iNdEx = postIndex
3327
+		default:
3328
+			iNdEx = preIndex
3329
+			skippy, err := skipGateway(dAtA[iNdEx:])
3330
+			if err != nil {
3331
+				return err
3332
+			}
3333
+			if skippy < 0 {
3334
+				return ErrInvalidLengthGateway
3335
+			}
3336
+			if (iNdEx + skippy) > l {
3337
+				return io.ErrUnexpectedEOF
3338
+			}
3339
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3340
+			iNdEx += skippy
3341
+		}
3342
+	}
3343
+
3344
+	if iNdEx > l {
3345
+		return io.ErrUnexpectedEOF
3346
+	}
3347
+	return nil
3348
+}
3062 3349
 func (m *ReturnRequest) Unmarshal(dAtA []byte) error {
3063 3350
 	l := len(dAtA)
3064 3351
 	iNdEx := 0
... ...
@@ -3227,6 +4231,231 @@ func (m *ReturnResponse) Unmarshal(dAtA []byte) error {
3227 3227
 	}
3228 3228
 	return nil
3229 3229
 }
3230
+func (m *InputsRequest) Unmarshal(dAtA []byte) error {
3231
+	l := len(dAtA)
3232
+	iNdEx := 0
3233
+	for iNdEx < l {
3234
+		preIndex := iNdEx
3235
+		var wire uint64
3236
+		for shift := uint(0); ; shift += 7 {
3237
+			if shift >= 64 {
3238
+				return ErrIntOverflowGateway
3239
+			}
3240
+			if iNdEx >= l {
3241
+				return io.ErrUnexpectedEOF
3242
+			}
3243
+			b := dAtA[iNdEx]
3244
+			iNdEx++
3245
+			wire |= (uint64(b) & 0x7F) << shift
3246
+			if b < 0x80 {
3247
+				break
3248
+			}
3249
+		}
3250
+		fieldNum := int32(wire >> 3)
3251
+		wireType := int(wire & 0x7)
3252
+		if wireType == 4 {
3253
+			return fmt.Errorf("proto: InputsRequest: wiretype end group for non-group")
3254
+		}
3255
+		if fieldNum <= 0 {
3256
+			return fmt.Errorf("proto: InputsRequest: illegal tag %d (wire type %d)", fieldNum, wire)
3257
+		}
3258
+		switch fieldNum {
3259
+		default:
3260
+			iNdEx = preIndex
3261
+			skippy, err := skipGateway(dAtA[iNdEx:])
3262
+			if err != nil {
3263
+				return err
3264
+			}
3265
+			if skippy < 0 {
3266
+				return ErrInvalidLengthGateway
3267
+			}
3268
+			if (iNdEx + skippy) > l {
3269
+				return io.ErrUnexpectedEOF
3270
+			}
3271
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3272
+			iNdEx += skippy
3273
+		}
3274
+	}
3275
+
3276
+	if iNdEx > l {
3277
+		return io.ErrUnexpectedEOF
3278
+	}
3279
+	return nil
3280
+}
3281
+func (m *InputsResponse) Unmarshal(dAtA []byte) error {
3282
+	l := len(dAtA)
3283
+	iNdEx := 0
3284
+	for iNdEx < l {
3285
+		preIndex := iNdEx
3286
+		var wire uint64
3287
+		for shift := uint(0); ; shift += 7 {
3288
+			if shift >= 64 {
3289
+				return ErrIntOverflowGateway
3290
+			}
3291
+			if iNdEx >= l {
3292
+				return io.ErrUnexpectedEOF
3293
+			}
3294
+			b := dAtA[iNdEx]
3295
+			iNdEx++
3296
+			wire |= (uint64(b) & 0x7F) << shift
3297
+			if b < 0x80 {
3298
+				break
3299
+			}
3300
+		}
3301
+		fieldNum := int32(wire >> 3)
3302
+		wireType := int(wire & 0x7)
3303
+		if wireType == 4 {
3304
+			return fmt.Errorf("proto: InputsResponse: wiretype end group for non-group")
3305
+		}
3306
+		if fieldNum <= 0 {
3307
+			return fmt.Errorf("proto: InputsResponse: illegal tag %d (wire type %d)", fieldNum, wire)
3308
+		}
3309
+		switch fieldNum {
3310
+		case 1:
3311
+			if wireType != 2 {
3312
+				return fmt.Errorf("proto: wrong wireType = %d for field Definitions", wireType)
3313
+			}
3314
+			var msglen int
3315
+			for shift := uint(0); ; shift += 7 {
3316
+				if shift >= 64 {
3317
+					return ErrIntOverflowGateway
3318
+				}
3319
+				if iNdEx >= l {
3320
+					return io.ErrUnexpectedEOF
3321
+				}
3322
+				b := dAtA[iNdEx]
3323
+				iNdEx++
3324
+				msglen |= (int(b) & 0x7F) << shift
3325
+				if b < 0x80 {
3326
+					break
3327
+				}
3328
+			}
3329
+			if msglen < 0 {
3330
+				return ErrInvalidLengthGateway
3331
+			}
3332
+			postIndex := iNdEx + msglen
3333
+			if postIndex > l {
3334
+				return io.ErrUnexpectedEOF
3335
+			}
3336
+			if m.Definitions == nil {
3337
+				m.Definitions = make(map[string]*pb.Definition)
3338
+			}
3339
+			var mapkey string
3340
+			var mapvalue *pb.Definition
3341
+			for iNdEx < postIndex {
3342
+				entryPreIndex := iNdEx
3343
+				var wire uint64
3344
+				for shift := uint(0); ; shift += 7 {
3345
+					if shift >= 64 {
3346
+						return ErrIntOverflowGateway
3347
+					}
3348
+					if iNdEx >= l {
3349
+						return io.ErrUnexpectedEOF
3350
+					}
3351
+					b := dAtA[iNdEx]
3352
+					iNdEx++
3353
+					wire |= (uint64(b) & 0x7F) << shift
3354
+					if b < 0x80 {
3355
+						break
3356
+					}
3357
+				}
3358
+				fieldNum := int32(wire >> 3)
3359
+				if fieldNum == 1 {
3360
+					var stringLenmapkey uint64
3361
+					for shift := uint(0); ; shift += 7 {
3362
+						if shift >= 64 {
3363
+							return ErrIntOverflowGateway
3364
+						}
3365
+						if iNdEx >= l {
3366
+							return io.ErrUnexpectedEOF
3367
+						}
3368
+						b := dAtA[iNdEx]
3369
+						iNdEx++
3370
+						stringLenmapkey |= (uint64(b) & 0x7F) << shift
3371
+						if b < 0x80 {
3372
+							break
3373
+						}
3374
+					}
3375
+					intStringLenmapkey := int(stringLenmapkey)
3376
+					if intStringLenmapkey < 0 {
3377
+						return ErrInvalidLengthGateway
3378
+					}
3379
+					postStringIndexmapkey := iNdEx + intStringLenmapkey
3380
+					if postStringIndexmapkey > l {
3381
+						return io.ErrUnexpectedEOF
3382
+					}
3383
+					mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
3384
+					iNdEx = postStringIndexmapkey
3385
+				} else if fieldNum == 2 {
3386
+					var mapmsglen int
3387
+					for shift := uint(0); ; shift += 7 {
3388
+						if shift >= 64 {
3389
+							return ErrIntOverflowGateway
3390
+						}
3391
+						if iNdEx >= l {
3392
+							return io.ErrUnexpectedEOF
3393
+						}
3394
+						b := dAtA[iNdEx]
3395
+						iNdEx++
3396
+						mapmsglen |= (int(b) & 0x7F) << shift
3397
+						if b < 0x80 {
3398
+							break
3399
+						}
3400
+					}
3401
+					if mapmsglen < 0 {
3402
+						return ErrInvalidLengthGateway
3403
+					}
3404
+					postmsgIndex := iNdEx + mapmsglen
3405
+					if mapmsglen < 0 {
3406
+						return ErrInvalidLengthGateway
3407
+					}
3408
+					if postmsgIndex > l {
3409
+						return io.ErrUnexpectedEOF
3410
+					}
3411
+					mapvalue = &pb.Definition{}
3412
+					if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil {
3413
+						return err
3414
+					}
3415
+					iNdEx = postmsgIndex
3416
+				} else {
3417
+					iNdEx = entryPreIndex
3418
+					skippy, err := skipGateway(dAtA[iNdEx:])
3419
+					if err != nil {
3420
+						return err
3421
+					}
3422
+					if skippy < 0 {
3423
+						return ErrInvalidLengthGateway
3424
+					}
3425
+					if (iNdEx + skippy) > postIndex {
3426
+						return io.ErrUnexpectedEOF
3427
+					}
3428
+					iNdEx += skippy
3429
+				}
3430
+			}
3431
+			m.Definitions[mapkey] = mapvalue
3432
+			iNdEx = postIndex
3433
+		default:
3434
+			iNdEx = preIndex
3435
+			skippy, err := skipGateway(dAtA[iNdEx:])
3436
+			if err != nil {
3437
+				return err
3438
+			}
3439
+			if skippy < 0 {
3440
+				return ErrInvalidLengthGateway
3441
+			}
3442
+			if (iNdEx + skippy) > l {
3443
+				return io.ErrUnexpectedEOF
3444
+			}
3445
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3446
+			iNdEx += skippy
3447
+		}
3448
+	}
3449
+
3450
+	if iNdEx > l {
3451
+		return io.ErrUnexpectedEOF
3452
+	}
3453
+	return nil
3454
+}
3230 3455
 func (m *ResolveImageConfigRequest) Unmarshal(dAtA []byte) error {
3231 3456
 	l := len(dAtA)
3232 3457
 	iNdEx := 0
... ...
@@ -3767,6 +4996,26 @@ func (m *SolveRequest) Unmarshal(dAtA []byte) error {
3767 3767
 				}
3768 3768
 			}
3769 3769
 			m.AllowResultReturn = bool(v != 0)
3770
+		case 6:
3771
+			if wireType != 0 {
3772
+				return fmt.Errorf("proto: wrong wireType = %d for field AllowResultArrayRef", wireType)
3773
+			}
3774
+			var v int
3775
+			for shift := uint(0); ; shift += 7 {
3776
+				if shift >= 64 {
3777
+					return ErrIntOverflowGateway
3778
+				}
3779
+				if iNdEx >= l {
3780
+					return io.ErrUnexpectedEOF
3781
+				}
3782
+				b := dAtA[iNdEx]
3783
+				iNdEx++
3784
+				v |= (int(b) & 0x7F) << shift
3785
+				if b < 0x80 {
3786
+					break
3787
+				}
3788
+			}
3789
+			m.AllowResultArrayRef = bool(v != 0)
3770 3790
 		case 10:
3771 3791
 			if wireType != 0 {
3772 3792
 				return fmt.Errorf("proto: wrong wireType = %d for field Final", wireType)
... ...
@@ -3849,6 +5098,129 @@ func (m *SolveRequest) Unmarshal(dAtA []byte) error {
3849 3849
 				return err
3850 3850
 			}
3851 3851
 			iNdEx = postIndex
3852
+		case 13:
3853
+			if wireType != 2 {
3854
+				return fmt.Errorf("proto: wrong wireType = %d for field FrontendInputs", wireType)
3855
+			}
3856
+			var msglen int
3857
+			for shift := uint(0); ; shift += 7 {
3858
+				if shift >= 64 {
3859
+					return ErrIntOverflowGateway
3860
+				}
3861
+				if iNdEx >= l {
3862
+					return io.ErrUnexpectedEOF
3863
+				}
3864
+				b := dAtA[iNdEx]
3865
+				iNdEx++
3866
+				msglen |= (int(b) & 0x7F) << shift
3867
+				if b < 0x80 {
3868
+					break
3869
+				}
3870
+			}
3871
+			if msglen < 0 {
3872
+				return ErrInvalidLengthGateway
3873
+			}
3874
+			postIndex := iNdEx + msglen
3875
+			if postIndex > l {
3876
+				return io.ErrUnexpectedEOF
3877
+			}
3878
+			if m.FrontendInputs == nil {
3879
+				m.FrontendInputs = make(map[string]*pb.Definition)
3880
+			}
3881
+			var mapkey string
3882
+			var mapvalue *pb.Definition
3883
+			for iNdEx < postIndex {
3884
+				entryPreIndex := iNdEx
3885
+				var wire uint64
3886
+				for shift := uint(0); ; shift += 7 {
3887
+					if shift >= 64 {
3888
+						return ErrIntOverflowGateway
3889
+					}
3890
+					if iNdEx >= l {
3891
+						return io.ErrUnexpectedEOF
3892
+					}
3893
+					b := dAtA[iNdEx]
3894
+					iNdEx++
3895
+					wire |= (uint64(b) & 0x7F) << shift
3896
+					if b < 0x80 {
3897
+						break
3898
+					}
3899
+				}
3900
+				fieldNum := int32(wire >> 3)
3901
+				if fieldNum == 1 {
3902
+					var stringLenmapkey uint64
3903
+					for shift := uint(0); ; shift += 7 {
3904
+						if shift >= 64 {
3905
+							return ErrIntOverflowGateway
3906
+						}
3907
+						if iNdEx >= l {
3908
+							return io.ErrUnexpectedEOF
3909
+						}
3910
+						b := dAtA[iNdEx]
3911
+						iNdEx++
3912
+						stringLenmapkey |= (uint64(b) & 0x7F) << shift
3913
+						if b < 0x80 {
3914
+							break
3915
+						}
3916
+					}
3917
+					intStringLenmapkey := int(stringLenmapkey)
3918
+					if intStringLenmapkey < 0 {
3919
+						return ErrInvalidLengthGateway
3920
+					}
3921
+					postStringIndexmapkey := iNdEx + intStringLenmapkey
3922
+					if postStringIndexmapkey > l {
3923
+						return io.ErrUnexpectedEOF
3924
+					}
3925
+					mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
3926
+					iNdEx = postStringIndexmapkey
3927
+				} else if fieldNum == 2 {
3928
+					var mapmsglen int
3929
+					for shift := uint(0); ; shift += 7 {
3930
+						if shift >= 64 {
3931
+							return ErrIntOverflowGateway
3932
+						}
3933
+						if iNdEx >= l {
3934
+							return io.ErrUnexpectedEOF
3935
+						}
3936
+						b := dAtA[iNdEx]
3937
+						iNdEx++
3938
+						mapmsglen |= (int(b) & 0x7F) << shift
3939
+						if b < 0x80 {
3940
+							break
3941
+						}
3942
+					}
3943
+					if mapmsglen < 0 {
3944
+						return ErrInvalidLengthGateway
3945
+					}
3946
+					postmsgIndex := iNdEx + mapmsglen
3947
+					if mapmsglen < 0 {
3948
+						return ErrInvalidLengthGateway
3949
+					}
3950
+					if postmsgIndex > l {
3951
+						return io.ErrUnexpectedEOF
3952
+					}
3953
+					mapvalue = &pb.Definition{}
3954
+					if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil {
3955
+						return err
3956
+					}
3957
+					iNdEx = postmsgIndex
3958
+				} else {
3959
+					iNdEx = entryPreIndex
3960
+					skippy, err := skipGateway(dAtA[iNdEx:])
3961
+					if err != nil {
3962
+						return err
3963
+					}
3964
+					if skippy < 0 {
3965
+						return ErrInvalidLengthGateway
3966
+					}
3967
+					if (iNdEx + skippy) > postIndex {
3968
+						return io.ErrUnexpectedEOF
3969
+					}
3970
+					iNdEx += skippy
3971
+				}
3972
+			}
3973
+			m.FrontendInputs[mapkey] = mapvalue
3974
+			iNdEx = postIndex
3852 3975
 		default:
3853 3976
 			iNdEx = preIndex
3854 3977
 			skippy, err := skipGateway(dAtA[iNdEx:])
... ...
@@ -5208,85 +6580,98 @@ var (
5208 5208
 	ErrIntOverflowGateway   = fmt.Errorf("proto: integer overflow")
5209 5209
 )
5210 5210
 
5211
-func init() { proto.RegisterFile("gateway.proto", fileDescriptor_gateway_eff078cadb286ceb) }
5212
-
5213
-var fileDescriptor_gateway_eff078cadb286ceb = []byte{
5214
-	// 1224 bytes of a gzipped FileDescriptorProto
5215
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xcd, 0x6e, 0xdb, 0xc6,
5216
-	0x13, 0x0f, 0x23, 0xc9, 0xb6, 0xc6, 0x72, 0xa2, 0x2c, 0xfe, 0xf8, 0x83, 0xe1, 0x21, 0x51, 0x89,
5217
-	0xc2, 0x55, 0x12, 0x87, 0x44, 0x9d, 0x16, 0x4e, 0x93, 0x22, 0x69, 0x14, 0x27, 0x88, 0x5b, 0xbb,
5218
-	0x11, 0x36, 0x05, 0x02, 0x04, 0x2d, 0xd0, 0x95, 0xb8, 0x62, 0x16, 0xa1, 0xb8, 0xec, 0x72, 0x15,
5219
-	0xd7, 0xe8, 0xa5, 0xed, 0x2b, 0xf4, 0x45, 0xfa, 0x18, 0xb9, 0xb5, 0xe7, 0x1e, 0x82, 0xc2, 0xb7,
5220
-	0x5e, 0xfa, 0x0c, 0xc5, 0x7e, 0x50, 0xa2, 0x3f, 0x44, 0x5b, 0x27, 0xee, 0x2c, 0xe7, 0x37, 0xf3,
5221
-	0x9b, 0xd9, 0x99, 0xd9, 0x85, 0xb5, 0x98, 0x48, 0xba, 0x4f, 0x0e, 0x82, 0x4c, 0x70, 0xc9, 0xd1,
5222
-	0xd5, 0x31, 0x1f, 0x1c, 0x04, 0x83, 0x09, 0x4b, 0xa2, 0x37, 0x4c, 0x06, 0x6f, 0x3f, 0x0e, 0x46,
5223
-	0x82, 0xa7, 0x92, 0xa6, 0x91, 0x77, 0x3b, 0x66, 0xf2, 0xf5, 0x64, 0x10, 0x0c, 0xf9, 0x38, 0x8c,
5224
-	0x79, 0xcc, 0x43, 0x8d, 0x18, 0x4c, 0x46, 0x5a, 0xd2, 0x82, 0x5e, 0x19, 0x4b, 0xde, 0xe6, 0x71,
5225
-	0xf5, 0x98, 0xf3, 0x38, 0xa1, 0x24, 0x63, 0xb9, 0x5d, 0x86, 0x22, 0x1b, 0x86, 0xb9, 0x24, 0x72,
5226
-	0x92, 0x5b, 0xcc, 0x46, 0x09, 0xa3, 0x88, 0x84, 0x05, 0x91, 0x30, 0xe7, 0xc9, 0x5b, 0x2a, 0xc2,
5227
-	0x6c, 0x10, 0xf2, 0xac, 0xd0, 0x0e, 0xe7, 0x6a, 0x93, 0x8c, 0x85, 0xf2, 0x20, 0xa3, 0x79, 0xb8,
5228
-	0xcf, 0xc5, 0x1b, 0x2a, 0x2c, 0xe0, 0xce, 0x5c, 0xc0, 0x44, 0xb2, 0x44, 0xa1, 0x86, 0x24, 0xcb,
5229
-	0x95, 0x13, 0xf5, 0xb5, 0xa0, 0x72, 0xd8, 0x92, 0xa7, 0x2c, 0x97, 0x8c, 0xc5, 0x2c, 0x1c, 0xe5,
5230
-	0x1a, 0x63, 0xbc, 0xa8, 0x20, 0x8c, 0xba, 0xff, 0x8f, 0x03, 0x4b, 0x98, 0xe6, 0x93, 0x44, 0x22,
5231
-	0x04, 0x35, 0x41, 0x47, 0xae, 0xd3, 0x71, 0xba, 0xcd, 0x67, 0x17, 0xb0, 0x12, 0xd0, 0x16, 0xd4,
5232
-	0x05, 0x1d, 0xe5, 0xee, 0xc5, 0x8e, 0xd3, 0x5d, 0xdd, 0xfc, 0x20, 0x98, 0x9b, 0xee, 0x00, 0xd3,
5233
-	0xd1, 0x1e, 0xc9, 0x9e, 0x5d, 0xc0, 0x1a, 0x80, 0xbe, 0x82, 0x95, 0x31, 0x95, 0x24, 0x22, 0x92,
5234
-	0xb8, 0xd0, 0xa9, 0x75, 0x57, 0x37, 0xc3, 0x4a, 0xb0, 0x62, 0x10, 0xec, 0x59, 0xc4, 0x93, 0x54,
5235
-	0x8a, 0x03, 0x3c, 0x35, 0xe0, 0xdd, 0x87, 0xb5, 0x23, 0xbf, 0x50, 0x1b, 0x6a, 0x6f, 0xe8, 0x81,
5236
-	0xa1, 0x8a, 0xd5, 0x12, 0xfd, 0x0f, 0x1a, 0x6f, 0x49, 0x32, 0xa1, 0x9a, 0x69, 0x0b, 0x1b, 0xe1,
5237
-	0xde, 0xc5, 0xbb, 0x4e, 0x6f, 0x05, 0x96, 0x84, 0x36, 0xef, 0xff, 0xaa, 0x63, 0x55, 0x34, 0xd1,
5238
-	0x43, 0x1b, 0x97, 0xa3, 0xa9, 0xdd, 0x3a, 0x33, 0x2e, 0xf5, 0xc9, 0x0d, 0x2d, 0x0d, 0xf4, 0xb6,
5239
-	0xa0, 0x39, 0xdd, 0x3a, 0x8b, 0x4e, 0xb3, 0x44, 0xc7, 0x97, 0xb0, 0x86, 0xa9, 0x9c, 0x88, 0x14,
5240
-	0xd3, 0x1f, 0x26, 0x34, 0x97, 0xe8, 0xb3, 0x82, 0x9f, 0xc6, 0x9f, 0x95, 0x64, 0xa5, 0x88, 0x2d,
5241
-	0x00, 0x75, 0xa1, 0x41, 0x85, 0xe0, 0xc2, 0x1e, 0x0f, 0x0a, 0x4c, 0xa1, 0x06, 0x22, 0x1b, 0x06,
5242
-	0x2f, 0x74, 0xa1, 0x62, 0xa3, 0xe0, 0xb7, 0xe1, 0x52, 0xe1, 0x35, 0xcf, 0x78, 0x9a, 0x53, 0xff,
5243
-	0x37, 0x07, 0xae, 0x62, 0xaa, 0xeb, 0x74, 0x67, 0x4c, 0x62, 0xfa, 0x98, 0xa7, 0x23, 0x16, 0x17,
5244
-	0xa4, 0xda, 0x50, 0xc3, 0x45, 0x2d, 0x60, 0xb5, 0x44, 0x5d, 0x58, 0xe9, 0x27, 0x44, 0x8e, 0xb8,
5245
-	0x18, 0x5b, 0x77, 0xad, 0x20, 0x1b, 0x04, 0xc5, 0x1e, 0x9e, 0xfe, 0x45, 0x1d, 0x58, 0xb5, 0x86,
5246
-	0xf7, 0x78, 0x44, 0xdd, 0x9a, 0xb6, 0x51, 0xde, 0x42, 0x2e, 0x2c, 0xef, 0xf2, 0xf8, 0x6b, 0x32,
5247
-	0xa6, 0x6e, 0x5d, 0xff, 0x2d, 0x44, 0xff, 0x67, 0x07, 0xbc, 0xd3, 0x58, 0x19, 0xd2, 0xe8, 0x4b,
5248
-	0x58, 0xda, 0x66, 0x31, 0xcd, 0x4d, 0xae, 0x9a, 0xbd, 0xcd, 0x77, 0xef, 0xaf, 0x5f, 0xf8, 0xeb,
5249
-	0xfd, 0xf5, 0x9b, 0xa5, 0xa2, 0xe7, 0x19, 0x4d, 0x87, 0x3c, 0x95, 0x84, 0xa5, 0x54, 0xa8, 0xde,
5250
-	0xbd, 0x1d, 0x69, 0x48, 0x60, 0x90, 0xd8, 0x5a, 0x40, 0xff, 0x87, 0x25, 0x63, 0xdd, 0x96, 0x8c,
5251
-	0x95, 0xfc, 0x7f, 0x6b, 0xd0, 0x7a, 0xa1, 0x08, 0x14, 0xb9, 0x08, 0x00, 0xb6, 0xe9, 0x88, 0xa5,
5252
-	0x4c, 0x32, 0x9e, 0xda, 0x43, 0xba, 0xa4, 0x62, 0x9f, 0xed, 0xe2, 0x92, 0x06, 0xf2, 0x60, 0xe5,
5253
-	0xa9, 0x3d, 0x30, 0x7b, 0xfc, 0x53, 0x19, 0xbd, 0x82, 0xd5, 0x62, 0xfd, 0x3c, 0x93, 0x6e, 0x4d,
5254
-	0x97, 0xdf, 0xdd, 0x8a, 0x13, 0x2f, 0x33, 0x09, 0x4a, 0x50, 0x53, 0x8b, 0x65, 0x63, 0xe8, 0x73,
5255
-	0xb8, 0xba, 0x33, 0xce, 0xb8, 0x90, 0x8f, 0xc9, 0xf0, 0x35, 0x55, 0xd5, 0xb9, 0x4d, 0x33, 0x41,
5256
-	0x87, 0x44, 0xd2, 0xc8, 0xad, 0x77, 0x6a, 0xdd, 0x26, 0x9e, 0xaf, 0x80, 0x36, 0xe0, 0x0a, 0x49,
5257
-	0x12, 0xbe, 0x6f, 0x4b, 0x4c, 0x17, 0x8b, 0xdb, 0xe8, 0x38, 0xdd, 0x15, 0x7c, 0xf2, 0x87, 0xaa,
5258
-	0xef, 0xa7, 0x2c, 0x25, 0x89, 0x0b, 0x5a, 0xc3, 0x08, 0xc8, 0x87, 0xd6, 0x93, 0x1f, 0x95, 0x03,
5259
-	0x2a, 0x1e, 0x49, 0x29, 0xdc, 0x55, 0x9d, 0xd8, 0x23, 0x7b, 0xa8, 0x0f, 0x2d, 0xed, 0xde, 0x30,
5260
-	0xc9, 0xdd, 0x96, 0x4e, 0xc1, 0x46, 0x45, 0x0a, 0xb4, 0xfa, 0xf3, 0x4c, 0xe5, 0xd6, 0xb6, 0xe0,
5261
-	0x11, 0x0b, 0xde, 0x03, 0x68, 0x1f, 0x4f, 0xcc, 0x42, 0x1d, 0xf9, 0xbb, 0x03, 0x57, 0x4e, 0xf8,
5262
-	0x40, 0x08, 0xea, 0xdf, 0x1c, 0x64, 0xd4, 0x9a, 0xd0, 0x6b, 0xb4, 0x07, 0x0d, 0x15, 0x83, 0x1a,
5263
-	0x87, 0x8a, 0xf4, 0xd6, 0x22, 0xa4, 0x03, 0x8d, 0x34, 0xfc, 0x8d, 0x15, 0xef, 0x2e, 0xc0, 0x6c,
5264
-	0x73, 0x21, 0xca, 0xdf, 0xc2, 0x9a, 0x2d, 0x0c, 0xdb, 0x18, 0xed, 0xd2, 0xec, 0x36, 0x93, 0x7b,
5265
-	0x36, 0x56, 0x6a, 0x0b, 0x8e, 0x15, 0xff, 0x27, 0xb8, 0x8c, 0x29, 0x89, 0x9e, 0xb2, 0x84, 0xce,
5266
-	0x9f, 0x07, 0xaa, 0xca, 0x59, 0x42, 0xfb, 0x44, 0xbe, 0x9e, 0x56, 0xb9, 0x95, 0xd1, 0x3d, 0x68,
5267
-	0x60, 0x92, 0xc6, 0xd4, 0xba, 0xfe, 0xb0, 0xc2, 0xb5, 0x76, 0xa2, 0x74, 0xb1, 0x81, 0xf8, 0xf7,
5268
-	0xa1, 0x39, 0xdd, 0x53, 0x3d, 0xfa, 0x7c, 0x34, 0xca, 0xa9, 0xe9, 0xf7, 0x1a, 0xb6, 0x92, 0xda,
5269
-	0xdf, 0xa5, 0x69, 0x6c, 0x5d, 0xd7, 0xb0, 0x95, 0xfc, 0x75, 0x68, 0xcf, 0x98, 0xdb, 0xd4, 0x20,
5270
-	0xa8, 0x6f, 0xab, 0x5b, 0xc8, 0xd1, 0xc5, 0xa8, 0xd7, 0x7e, 0xa4, 0xc6, 0x21, 0x89, 0xb6, 0x99,
5271
-	0x98, 0x1f, 0xa0, 0x0b, 0xcb, 0xdb, 0x4c, 0x94, 0xe2, 0x2b, 0x44, 0xb4, 0x0e, 0x97, 0x76, 0xd2,
5272
-	0x61, 0x32, 0x89, 0x54, 0xb4, 0x92, 0x8a, 0xd4, 0xce, 0xb8, 0x63, 0xbb, 0xfe, 0x43, 0x93, 0x47,
5273
-	0xed, 0xc5, 0x92, 0xd9, 0x80, 0x65, 0x9a, 0x4a, 0xc1, 0x68, 0x71, 0xf5, 0xa0, 0xc0, 0xdc, 0xcc,
5274
-	0x81, 0xbe, 0x99, 0xf5, 0xd4, 0xc6, 0x85, 0x8a, 0xbf, 0x05, 0x97, 0xd5, 0x46, 0xf5, 0x41, 0x20,
5275
-	0xa8, 0x97, 0x48, 0xea, 0xb5, 0x7f, 0x0f, 0xda, 0x33, 0xa0, 0x75, 0xbd, 0x0e, 0x75, 0x75, 0xef,
5276
-	0xdb, 0x01, 0x76, 0x9a, 0x5f, 0xfd, 0xdf, 0x5f, 0x83, 0xd5, 0x3e, 0x4b, 0x8b, 0x9b, 0xc0, 0x3f,
5277
-	0x74, 0xa0, 0xd5, 0xe7, 0xe9, 0x6c, 0x06, 0xf7, 0xe1, 0x72, 0xd1, 0x6e, 0x8f, 0xfa, 0x3b, 0x8f,
5278
-	0x49, 0x56, 0x84, 0xd2, 0x39, 0x79, 0xcc, 0xf6, 0x89, 0x12, 0x18, 0xc5, 0x5e, 0x5d, 0x8d, 0x6b,
5279
-	0x7c, 0x1c, 0x8e, 0xbe, 0x80, 0xe5, 0xdd, 0xdd, 0x9e, 0xb6, 0x74, 0x71, 0x21, 0x4b, 0x05, 0x0c,
5280
-	0x3d, 0x80, 0xe5, 0x97, 0xfa, 0xe5, 0x94, 0xdb, 0x91, 0x7a, 0x4a, 0xc9, 0x99, 0x40, 0x8d, 0x1a,
5281
-	0xa6, 0x43, 0x2e, 0x22, 0x5c, 0x80, 0x36, 0xff, 0x68, 0x40, 0x73, 0x77, 0xb7, 0xd7, 0x13, 0x2c,
5282
-	0x8a, 0x29, 0xfa, 0xc5, 0x01, 0x74, 0xf2, 0x12, 0x42, 0x9f, 0x54, 0x77, 0xd0, 0xe9, 0x37, 0xa9,
5283
-	0xf7, 0xe9, 0x82, 0x28, 0x9b, 0xe5, 0x57, 0xd0, 0xd0, 0x1d, 0x8e, 0x3e, 0x3a, 0xe7, 0xe5, 0xe0,
5284
-	0x75, 0xcf, 0x56, 0xb4, 0xb6, 0x87, 0xb0, 0x52, 0x74, 0x09, 0xba, 0x59, 0x49, 0xef, 0xc8, 0x10,
5285
-	0xf0, 0x6e, 0x9d, 0x4b, 0xd7, 0x3a, 0xf9, 0x1e, 0x96, 0x6d, 0xf1, 0xa3, 0x1b, 0x67, 0xe0, 0x66,
5286
-	0x6d, 0xe8, 0xdd, 0x3c, 0x8f, 0xea, 0x2c, 0x8c, 0xa2, 0xc8, 0x2b, 0xc3, 0x38, 0xd6, 0x42, 0x95,
5287
-	0x61, 0x9c, 0xe8, 0x9a, 0x97, 0x50, 0x57, 0xdd, 0x80, 0xd6, 0x2b, 0x40, 0xa5, 0x76, 0xf1, 0xaa,
5288
-	0x8e, 0xeb, 0x48, 0x1b, 0x7d, 0xa7, 0xde, 0xa2, 0xfa, 0x2e, 0xed, 0x56, 0xc6, 0x5c, 0x7a, 0x2a,
5289
-	0x7a, 0x37, 0xce, 0xa1, 0x69, 0xcc, 0xf7, 0x5a, 0xef, 0x0e, 0xaf, 0x39, 0x7f, 0x1e, 0x5e, 0x73,
5290
-	0xfe, 0x3e, 0xbc, 0xe6, 0x0c, 0x96, 0xf4, 0x63, 0xff, 0xce, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff,
5291
-	0x7c, 0xf6, 0x53, 0x84, 0x3e, 0x0d, 0x00, 0x00,
5211
+func init() { proto.RegisterFile("gateway.proto", fileDescriptor_gateway_20a4d16709b1a720) }
5212
+
5213
+var fileDescriptor_gateway_20a4d16709b1a720 = []byte{
5214
+	// 1436 bytes of a gzipped FileDescriptorProto
5215
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x57, 0xcd, 0x6e, 0xdb, 0xc6,
5216
+	0x16, 0x36, 0xad, 0x1f, 0x5b, 0x47, 0x92, 0xad, 0x4c, 0x2e, 0x2e, 0x14, 0x2e, 0x1c, 0x5d, 0x22,
5217
+	0xf0, 0x55, 0x12, 0x87, 0x6a, 0x9d, 0x04, 0x4e, 0x9d, 0x22, 0x69, 0x14, 0x27, 0xb0, 0x5b, 0x3b,
5218
+	0x51, 0x27, 0x2d, 0x02, 0x04, 0x29, 0x50, 0x4a, 0x1c, 0x32, 0x44, 0x24, 0x0e, 0x3b, 0x1c, 0x25,
5219
+	0x15, 0xba, 0x69, 0x77, 0xdd, 0x17, 0xe8, 0x03, 0xf4, 0x01, 0x8a, 0x3e, 0x41, 0xd7, 0x59, 0x76,
5220
+	0x59, 0x74, 0x11, 0x14, 0x7e, 0x92, 0x62, 0x7e, 0x68, 0x51, 0xb2, 0x4c, 0x59, 0xe8, 0x4a, 0x33,
5221
+	0x87, 0xe7, 0x3b, 0x73, 0xce, 0x37, 0xe7, 0x67, 0x04, 0x55, 0xdf, 0xe1, 0xe4, 0xad, 0x33, 0xb2,
5222
+	0x23, 0x46, 0x39, 0x45, 0x97, 0x06, 0xb4, 0x3b, 0xb2, 0xbb, 0xc3, 0xa0, 0xef, 0xbe, 0x0e, 0xb8,
5223
+	0xfd, 0xe6, 0x43, 0xdb, 0x63, 0x34, 0xe4, 0x24, 0x74, 0xcd, 0x1b, 0x7e, 0xc0, 0x5f, 0x0d, 0xbb,
5224
+	0x76, 0x8f, 0x0e, 0x5a, 0x3e, 0xf5, 0x69, 0x4b, 0x22, 0xba, 0x43, 0x4f, 0xee, 0xe4, 0x46, 0xae,
5225
+	0x94, 0x25, 0x73, 0x7b, 0x5a, 0xdd, 0xa7, 0xd4, 0xef, 0x13, 0x27, 0x0a, 0x62, 0xbd, 0x6c, 0xb1,
5226
+	0xa8, 0xd7, 0x8a, 0xb9, 0xc3, 0x87, 0xb1, 0xc6, 0x6c, 0xa5, 0x30, 0xc2, 0x91, 0x56, 0xe2, 0x48,
5227
+	0x2b, 0xa6, 0xfd, 0x37, 0x84, 0xb5, 0xa2, 0x6e, 0x8b, 0x46, 0x89, 0x76, 0xeb, 0x4c, 0x6d, 0x27,
5228
+	0x0a, 0x5a, 0x7c, 0x14, 0x91, 0xb8, 0xf5, 0x96, 0xb2, 0xd7, 0x84, 0x69, 0xc0, 0xcd, 0x33, 0x01,
5229
+	0x43, 0x1e, 0xf4, 0x05, 0xaa, 0xe7, 0x44, 0xb1, 0x38, 0x44, 0xfc, 0x6a, 0x50, 0x3a, 0x6c, 0x4e,
5230
+	0xc3, 0x20, 0xe6, 0x41, 0xe0, 0x07, 0x2d, 0x2f, 0x96, 0x18, 0x75, 0x8a, 0x08, 0x42, 0xa9, 0x5b,
5231
+	0x3f, 0xe6, 0xa0, 0x88, 0x49, 0x3c, 0xec, 0x73, 0xb4, 0x09, 0x55, 0x46, 0xbc, 0x3d, 0x12, 0x31,
5232
+	0xd2, 0x73, 0x38, 0x71, 0xeb, 0x46, 0xc3, 0x68, 0x96, 0xf6, 0x97, 0xf0, 0xa4, 0x18, 0x7d, 0x09,
5233
+	0x6b, 0x8c, 0x78, 0x71, 0x4a, 0x71, 0xb9, 0x61, 0x34, 0xcb, 0xdb, 0xd7, 0xed, 0x33, 0x2f, 0xc3,
5234
+	0xc6, 0xc4, 0x3b, 0x72, 0xa2, 0x31, 0x64, 0x7f, 0x09, 0x4f, 0x19, 0x41, 0xdb, 0x90, 0x63, 0xc4,
5235
+	0xab, 0xe7, 0xa4, 0xad, 0x8d, 0x6c, 0x5b, 0xfb, 0x4b, 0x58, 0x28, 0xa3, 0x1d, 0xc8, 0x0b, 0x2b,
5236
+	0xf5, 0xbc, 0x04, 0xfd, 0x6f, 0xae, 0x03, 0xfb, 0x4b, 0x58, 0x02, 0xd0, 0x67, 0xb0, 0x3a, 0x20,
5237
+	0xdc, 0x71, 0x1d, 0xee, 0xd4, 0xa1, 0x91, 0x6b, 0x96, 0xb7, 0x5b, 0x99, 0x60, 0x41, 0x90, 0x7d,
5238
+	0xa4, 0x11, 0x8f, 0x42, 0xce, 0x46, 0xf8, 0xc4, 0x80, 0x79, 0x17, 0xaa, 0x13, 0x9f, 0x50, 0x0d,
5239
+	0x72, 0xaf, 0xc9, 0x48, 0xf1, 0x87, 0xc5, 0x12, 0xfd, 0x07, 0x0a, 0x6f, 0x9c, 0xfe, 0x90, 0x48,
5240
+	0xaa, 0x2a, 0x58, 0x6d, 0x76, 0x97, 0xef, 0x18, 0xed, 0x55, 0x28, 0x32, 0x69, 0xde, 0xfa, 0xd9,
5241
+	0x80, 0xda, 0x34, 0x4f, 0xe8, 0x40, 0x47, 0x68, 0x48, 0x27, 0x6f, 0x2f, 0x40, 0xb1, 0x10, 0xc4,
5242
+	0xca, 0x55, 0x69, 0xc2, 0xdc, 0x81, 0xd2, 0x89, 0x68, 0x9e, 0x8b, 0xa5, 0x94, 0x8b, 0xd6, 0x0e,
5243
+	0xe4, 0x30, 0xf1, 0xd0, 0x1a, 0x2c, 0x07, 0x3a, 0x29, 0xf0, 0x72, 0xe0, 0xa2, 0x06, 0xe4, 0x5c,
5244
+	0xe2, 0xe9, 0xcb, 0x5f, 0xb3, 0xa3, 0xae, 0xbd, 0x47, 0xbc, 0x20, 0x0c, 0x78, 0x40, 0x43, 0x2c,
5245
+	0x3e, 0x59, 0xbf, 0x18, 0x22, 0xb9, 0x84, 0x5b, 0xe8, 0xfe, 0x44, 0x1c, 0xf3, 0x53, 0xe5, 0x94,
5246
+	0xf7, 0xcf, 0xb3, 0xbd, 0xbf, 0x95, 0xf6, 0x7e, 0x6e, 0xfe, 0xa4, 0xa3, 0xe3, 0x50, 0xc5, 0x84,
5247
+	0x0f, 0x59, 0x88, 0xc9, 0x37, 0x43, 0x12, 0x73, 0xf4, 0x51, 0x72, 0x23, 0xd2, 0xfe, 0xbc, 0xb4,
5248
+	0x12, 0x8a, 0x58, 0x03, 0x50, 0x13, 0x0a, 0x84, 0x31, 0xca, 0xb4, 0x17, 0xc8, 0x56, 0x9d, 0xc3,
5249
+	0x66, 0x51, 0xcf, 0x7e, 0x26, 0x3b, 0x07, 0x56, 0x0a, 0x56, 0x0d, 0xd6, 0x92, 0x53, 0xe3, 0x88,
5250
+	0x86, 0x31, 0xb1, 0xd6, 0xa1, 0x7a, 0x10, 0x46, 0x43, 0x1e, 0x6b, 0x3f, 0xac, 0xdf, 0x0d, 0x58,
5251
+	0x4b, 0x24, 0x4a, 0x07, 0xbd, 0x84, 0xf2, 0x98, 0xe3, 0x84, 0xcc, 0xdd, 0x0c, 0xff, 0x26, 0xf1,
5252
+	0xa9, 0x0b, 0xd2, 0xdc, 0xa6, 0xcd, 0x99, 0x4f, 0xa0, 0x36, 0xad, 0x30, 0x83, 0xe9, 0x2b, 0x93,
5253
+	0x4c, 0x4f, 0x5f, 0x7c, 0x8a, 0xd9, 0x9f, 0x0c, 0xb8, 0x84, 0x89, 0x6c, 0x85, 0x07, 0x03, 0xc7,
5254
+	0x27, 0x0f, 0x69, 0xe8, 0x05, 0x7e, 0x42, 0x73, 0x4d, 0x66, 0x55, 0x62, 0x59, 0x24, 0x58, 0x13,
5255
+	0x56, 0x3b, 0x7d, 0x87, 0x7b, 0x94, 0x0d, 0xb4, 0xf1, 0x8a, 0x30, 0x9e, 0xc8, 0xf0, 0xc9, 0x57,
5256
+	0xd4, 0x80, 0xb2, 0x36, 0x7c, 0x44, 0x5d, 0x22, 0x7b, 0x46, 0x09, 0xa7, 0x45, 0xa8, 0x0e, 0x2b,
5257
+	0x87, 0xd4, 0x7f, 0xe2, 0x0c, 0x88, 0x6c, 0x0e, 0x25, 0x9c, 0x6c, 0xad, 0xef, 0x0d, 0x30, 0x67,
5258
+	0x79, 0xa5, 0x29, 0xfe, 0x14, 0x8a, 0x7b, 0x81, 0x4f, 0x62, 0x75, 0xfb, 0xa5, 0xf6, 0xf6, 0xbb,
5259
+	0xf7, 0x97, 0x97, 0xfe, 0x7a, 0x7f, 0xf9, 0x5a, 0xaa, 0xaf, 0xd2, 0x88, 0x84, 0x3d, 0x1a, 0x72,
5260
+	0x27, 0x08, 0x09, 0x13, 0xe3, 0xe1, 0x86, 0x2b, 0x21, 0xb6, 0x42, 0x62, 0x6d, 0x01, 0xfd, 0x17,
5261
+	0x8a, 0xca, 0xba, 0x2e, 0x7b, 0xbd, 0xb3, 0xfe, 0x2c, 0x40, 0xe5, 0x99, 0x70, 0x20, 0xe1, 0xc2,
5262
+	0x06, 0x18, 0x53, 0xa8, 0xd3, 0x6e, 0x9a, 0xd8, 0x94, 0x06, 0x32, 0x61, 0xf5, 0xb1, 0xbe, 0x62,
5263
+	0x5d, 0xae, 0x27, 0x7b, 0xf4, 0x02, 0xca, 0xc9, 0xfa, 0x69, 0xc4, 0xeb, 0x39, 0x99, 0x23, 0x77,
5264
+	0x32, 0x72, 0x24, 0xed, 0x89, 0x9d, 0x82, 0xea, 0x0c, 0x49, 0x49, 0xd0, 0xc7, 0x70, 0xe9, 0x60,
5265
+	0x10, 0x51, 0xc6, 0x1f, 0x3a, 0xbd, 0x57, 0x04, 0x4f, 0x4e, 0x81, 0x7c, 0x23, 0xd7, 0x2c, 0xe1,
5266
+	0xb3, 0x15, 0xd0, 0x16, 0x5c, 0x70, 0xfa, 0x7d, 0xfa, 0x56, 0x17, 0x8d, 0x4c, 0xff, 0x7a, 0xa1,
5267
+	0x61, 0x34, 0x57, 0xf1, 0xe9, 0x0f, 0xe8, 0x03, 0xb8, 0x98, 0x12, 0x3e, 0x60, 0xcc, 0x19, 0x89,
5268
+	0x7c, 0x29, 0x4a, 0xfd, 0x59, 0x9f, 0x44, 0x07, 0x7b, 0x1c, 0x84, 0x4e, 0xbf, 0x0e, 0x52, 0x47,
5269
+	0x6d, 0x90, 0x05, 0x95, 0x47, 0xdf, 0x0a, 0x97, 0x08, 0x7b, 0xc0, 0x39, 0xab, 0x97, 0xe5, 0x55,
5270
+	0x4c, 0xc8, 0x50, 0x07, 0x2a, 0xd2, 0x61, 0xe5, 0x7b, 0x5c, 0xaf, 0x48, 0xd2, 0xb6, 0x32, 0x48,
5271
+	0x93, 0xea, 0x4f, 0xa3, 0x54, 0x29, 0x4d, 0x58, 0x40, 0x3d, 0x58, 0x4b, 0x88, 0x53, 0x35, 0x58,
5272
+	0xaf, 0x4a, 0x9b, 0x77, 0x17, 0xbd, 0x08, 0x85, 0x56, 0x47, 0x4c, 0x99, 0x34, 0xef, 0x41, 0x6d,
5273
+	0xfa, 0xbe, 0x16, 0x69, 0xec, 0xe6, 0xe7, 0x70, 0x71, 0xc6, 0x31, 0xff, 0xaa, 0xe6, 0x7f, 0x33,
5274
+	0xe0, 0xc2, 0x29, 0x6e, 0x10, 0x82, 0xfc, 0x17, 0xa3, 0x88, 0x68, 0x93, 0x72, 0x8d, 0x8e, 0xa0,
5275
+	0x20, 0xb8, 0x8f, 0xeb, 0xcb, 0x92, 0x98, 0x9d, 0x45, 0xc8, 0xb6, 0x25, 0x52, 0x91, 0xa2, 0xac,
5276
+	0x98, 0x77, 0x00, 0xc6, 0xc2, 0x85, 0xc6, 0xdb, 0x4b, 0xa8, 0x6a, 0xe6, 0x75, 0x0b, 0xa8, 0xa9,
5277
+	0x97, 0x88, 0x06, 0x8b, 0x77, 0xc6, 0x78, 0x24, 0xe4, 0x16, 0x1c, 0x09, 0xd6, 0x77, 0xb0, 0x8e,
5278
+	0x89, 0xe3, 0x3e, 0x0e, 0xfa, 0xe4, 0xec, 0xce, 0x27, 0xea, 0x39, 0xe8, 0x93, 0x8e, 0xc3, 0x5f,
5279
+	0x9d, 0xd4, 0xb3, 0xde, 0xa3, 0x5d, 0x28, 0x60, 0x27, 0xf4, 0x89, 0x3e, 0xfa, 0x4a, 0xc6, 0xd1,
5280
+	0xf2, 0x10, 0xa1, 0x8b, 0x15, 0xc4, 0xba, 0x0b, 0xa5, 0x13, 0x99, 0xe8, 0x46, 0x4f, 0x3d, 0x2f,
5281
+	0x26, 0xaa, 0xb3, 0xe5, 0xb0, 0xde, 0x09, 0xf9, 0x21, 0x09, 0x7d, 0x7d, 0x74, 0x0e, 0xeb, 0x9d,
5282
+	0xb5, 0x29, 0x9e, 0x23, 0x89, 0xe7, 0x9a, 0x1a, 0x04, 0xf9, 0x3d, 0xf1, 0x66, 0x32, 0x64, 0x11,
5283
+	0xc9, 0xb5, 0xe5, 0x8a, 0x51, 0xe6, 0xb8, 0x7b, 0x01, 0x3b, 0x3b, 0xc0, 0x3a, 0xac, 0xec, 0x05,
5284
+	0x2c, 0x15, 0x5f, 0xb2, 0x45, 0x9b, 0x62, 0xc8, 0xf5, 0xfa, 0x43, 0x57, 0x44, 0xcb, 0x09, 0x0b,
5285
+	0x75, 0x37, 0x9f, 0x92, 0x5a, 0xf7, 0x15, 0x8f, 0xf2, 0x14, 0xed, 0xcc, 0x16, 0xac, 0x90, 0x90,
5286
+	0xb3, 0x80, 0x24, 0x93, 0x10, 0xd9, 0xea, 0x99, 0x6b, 0xcb, 0x67, 0xae, 0x9c, 0xb8, 0x38, 0x51,
5287
+	0xb1, 0x76, 0x60, 0x5d, 0x08, 0xb2, 0x2f, 0x02, 0x41, 0x3e, 0xe5, 0xa4, 0x5c, 0x5b, 0xbb, 0x50,
5288
+	0x1b, 0x03, 0xf5, 0xd1, 0x9b, 0x90, 0x17, 0x8f, 0x68, 0xdd, 0xaa, 0x67, 0x9d, 0x2b, 0xbf, 0x5b,
5289
+	0x55, 0x28, 0x77, 0x82, 0x30, 0x99, 0x79, 0xd6, 0xb1, 0x01, 0x95, 0x0e, 0x0d, 0xc7, 0xd3, 0xa6,
5290
+	0x03, 0xeb, 0x49, 0x05, 0x3e, 0xe8, 0x1c, 0x3c, 0x74, 0xa2, 0x24, 0x94, 0xc6, 0xe9, 0x6b, 0xd6,
5291
+	0xef, 0x7d, 0x5b, 0x29, 0xb6, 0xf3, 0x62, 0x30, 0xe1, 0x69, 0x38, 0xfa, 0x04, 0x56, 0x0e, 0x0f,
5292
+	0xdb, 0xd2, 0xd2, 0xf2, 0x42, 0x96, 0x12, 0x18, 0xba, 0x07, 0x2b, 0xcf, 0xe5, 0xdf, 0x90, 0x58,
5293
+	0x0f, 0x8f, 0x19, 0x29, 0xa7, 0x02, 0x55, 0x6a, 0x98, 0xf4, 0x28, 0x73, 0x71, 0x02, 0xda, 0xfe,
5294
+	0xb5, 0x08, 0xa5, 0xc3, 0xc3, 0x76, 0x9b, 0x05, 0xae, 0x4f, 0xd0, 0x0f, 0x06, 0xa0, 0xd3, 0xe3,
5295
+	0x16, 0xdd, 0xca, 0xae, 0xa0, 0xd9, 0x6f, 0x06, 0xf3, 0xf6, 0x82, 0x28, 0xcd, 0xf2, 0x0b, 0x28,
5296
+	0xc8, 0x0a, 0x47, 0xff, 0x3f, 0x67, 0xf7, 0x35, 0x9b, 0xf3, 0x15, 0xb5, 0xed, 0x1e, 0xac, 0x26,
5297
+	0x55, 0x82, 0xae, 0x65, 0xba, 0x37, 0xd1, 0x04, 0xcc, 0xeb, 0xe7, 0xd2, 0xd5, 0x87, 0x7c, 0x0d,
5298
+	0x2b, 0x3a, 0xf9, 0xd1, 0xd5, 0x39, 0xb8, 0x71, 0x19, 0x9a, 0xd7, 0xce, 0xa3, 0x3a, 0x0e, 0x23,
5299
+	0x49, 0xf2, 0xcc, 0x30, 0xa6, 0x4a, 0x28, 0x33, 0x8c, 0x53, 0x55, 0xf3, 0x1c, 0xf2, 0xa2, 0x1a,
5300
+	0xd0, 0x66, 0x06, 0x28, 0x55, 0x2e, 0x66, 0xd6, 0x75, 0x4d, 0x94, 0xd1, 0x57, 0xe2, 0x7f, 0x86,
5301
+	0x7c, 0x35, 0x34, 0x33, 0x63, 0x4e, 0x3d, 0xf3, 0xcd, 0xab, 0xe7, 0xd0, 0x1c, 0x9b, 0x57, 0xf3,
5302
+	0x31, 0xd3, 0xfc, 0xc4, 0xeb, 0x3d, 0xd3, 0xfc, 0xe4, 0xab, 0xbc, 0x5d, 0x79, 0x77, 0xbc, 0x61,
5303
+	0xfc, 0x71, 0xbc, 0x61, 0xfc, 0x7d, 0xbc, 0x61, 0x74, 0x8b, 0xf2, 0x8f, 0xf9, 0xcd, 0x7f, 0x02,
5304
+	0x00, 0x00, 0xff, 0xff, 0xa9, 0x05, 0x0f, 0x9d, 0xea, 0x10, 0x00, 0x00,
5292 5305
 }
... ...
@@ -26,20 +26,35 @@ service LLBBridge {
26 26
 	rpc StatFile(StatFileRequest) returns (StatFileResponse);
27 27
 	rpc Ping(PingRequest) returns (PongResponse);
28 28
 	rpc Return(ReturnRequest) returns (ReturnResponse);
29
+	// apicaps:CapFrontendInputs
30
+	rpc Inputs(InputsRequest) returns (InputsResponse);
29 31
 }
30 32
 
31 33
 message Result {
32 34
 	oneof result {
33
-		string ref = 1;
34
-		RefMap refs = 2;
35
+    		// Deprecated non-array refs.
36
+		string refDeprecated = 1;
37
+		RefMapDeprecated refsDeprecated = 2;
38
+
39
+		Ref ref = 3;
40
+		RefMap refs = 4;
35 41
 	}
36 42
 	map<string, bytes> metadata = 10;
37 43
 }
38 44
 
39
-message RefMap {
45
+message RefMapDeprecated {
40 46
 	map<string, string> refs = 1;
41 47
 }
42 48
 
49
+message Ref {
50
+	string id = 1;
51
+	pb.Definition def = 2;
52
+}
53
+
54
+message RefMap {
55
+	map<string, Ref> refs = 1;
56
+}
57
+
43 58
 message ReturnRequest {
44 59
 	Result result = 1;
45 60
 	google.rpc.Status error = 2;
... ...
@@ -48,6 +63,13 @@ message ReturnRequest {
48 48
 message ReturnResponse {
49 49
 }
50 50
 
51
+message InputsRequest {
52
+}
53
+
54
+message InputsResponse {
55
+    map<string, pb.Definition> Definitions = 1;
56
+}
57
+
51 58
 message ResolveImageConfigRequest {
52 59
 	string Ref = 1;
53 60
 	pb.Platform Platform = 2;
... ...
@@ -70,6 +92,7 @@ message SolveRequest {
70 70
         // for each of the ImportCacheRefs entry to CacheImports for compatibility. (planned to be removed)
71 71
 	repeated string ImportCacheRefsDeprecated = 4;
72 72
 	bool allowResultReturn = 5;
73
+	bool allowResultArrayRef = 6;
73 74
 	
74 75
 	// apicaps.CapSolveInlineReturn deprecated
75 76
 	bool Final = 10;
... ...
@@ -77,6 +100,9 @@ message SolveRequest {
77 77
 	// CacheImports was added in BuildKit v0.4.0.
78 78
 	// apicaps:CapImportCaches
79 79
 	repeated CacheOptionsEntry CacheImports = 12;
80
+
81
+	// apicaps:CapFrontendInputs
82
+	map<string, pb.Definition> FrontendInputs = 13;
80 83
 }
81 84
 
82 85
 // CacheOptionsEntry corresponds to the control.CacheOptionsEntry
... ...
@@ -1,14 +1,16 @@
1 1
 package frontend
2 2
 
3
-import "github.com/moby/buildkit/solver"
3
+import (
4
+	"github.com/moby/buildkit/solver"
5
+)
4 6
 
5 7
 type Result struct {
6
-	Ref      solver.CachedResult
7
-	Refs     map[string]solver.CachedResult
8
+	Ref      solver.ResultProxy
9
+	Refs     map[string]solver.ResultProxy
8 10
 	Metadata map[string][]byte
9 11
 }
10 12
 
11
-func (r *Result) EachRef(fn func(solver.CachedResult) error) (err error) {
13
+func (r *Result) EachRef(fn func(solver.ResultProxy) error) (err error) {
12 14
 	if r.Ref != nil {
13 15
 		err = fn(r.Ref)
14 16
 	}
... ...
@@ -1,23 +1,25 @@
1 1
 module github.com/moby/buildkit
2 2
 
3
-go 1.11
3
+go 1.12
4 4
 
5 5
 require (
6 6
 	github.com/BurntSushi/toml v0.3.1
7 7
 	github.com/Microsoft/go-winio v0.4.14
8
+	github.com/Microsoft/hcsshim v0.8.5 // indirect
8 9
 	github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7 // indirect
9 10
 	github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58 // indirect
10 11
 	github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601 // indirect
11 12
 	github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50
12 13
 	github.com/containerd/containerd v1.4.0-0.20191014053712-acdcf13d5eaf
13
-	github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6
14
+	github.com/containerd/continuity v0.0.0-20200107194136-26c1120b8d41
14 15
 	github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c // indirect
15 16
 	github.com/containerd/go-cni v0.0.0-20190813230227-49fbd9b210f3
16 17
 	github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda
17 18
 	github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8 // indirect
18 19
 	github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd // indirect
19 20
 	github.com/containernetworking/cni v0.7.1 // indirect
20
-	github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a
21
+	github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a // indirect
22
+	github.com/coreos/go-systemd/v22 v22.0.0
21 23
 	github.com/docker/cli v0.0.0-20190321234815-f40f9c240ab0
22 24
 	github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible
23 25
 	github.com/docker/docker v1.14.0-0.20190319215453-e7b5f7dbe98c
... ...
@@ -53,9 +55,9 @@ require (
53 53
 	github.com/prometheus/procfs v0.0.3 // indirect
54 54
 	github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002
55 55
 	github.com/sirupsen/logrus v1.4.1
56
-	github.com/stretchr/testify v1.3.0
56
+	github.com/stretchr/testify v1.4.0
57 57
 	github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 // indirect
58
-	github.com/tonistiigi/fsutil v0.0.0-20190819224149-3d2716dd0a4d
58
+	github.com/tonistiigi/fsutil v0.0.0-20200128191323-6c909ab392c1
59 59
 	github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea
60 60
 	github.com/uber/jaeger-client-go v0.0.0-20180103221425-e02c85f9069e
61 61
 	github.com/uber/jaeger-lib v1.2.1 // indirect
... ...
@@ -63,7 +65,7 @@ require (
63 63
 	github.com/vishvananda/netlink v1.0.0 // indirect
64 64
 	github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect
65 65
 	go.etcd.io/bbolt v1.3.3
66
-	golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
66
+	golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6
67 67
 	golang.org/x/net v0.0.0-20190522155817-f3200d17e092
68 68
 	golang.org/x/sync v0.0.0-20190423024810-112230192c58
69 69
 	golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e
... ...
@@ -75,6 +75,10 @@ func MountSSHSocket(ctx context.Context, c session.Caller, opt SocketOpt) (sockP
75 75
 		}
76 76
 	}()
77 77
 
78
+	if err := os.Chmod(dir, 0711); err != nil {
79
+		return "", nil, errors.WithStack(err)
80
+	}
81
+
78 82
 	sockPath = filepath.Join(dir, "ssh_auth_sock")
79 83
 
80 84
 	l, err := net.Listen("unix", sockPath)
... ...
@@ -87,6 +87,9 @@ func (cm *combinedCacheManager) Load(ctx context.Context, rec *CacheRecord) (res
87 87
 			}
88 88
 		}
89 89
 	}
90
+	if len(results) == 0 { // TODO: handle gracefully
91
+		return nil, errors.Errorf("failed to load deleted cache")
92
+	}
90 93
 	return results[0].Result, nil
91 94
 }
92 95
 
... ...
@@ -9,14 +9,17 @@ import (
9 9
 	"time"
10 10
 
11 11
 	"github.com/containerd/containerd/platforms"
12
+	"github.com/mitchellh/hashstructure"
12 13
 	"github.com/moby/buildkit/cache"
13 14
 	"github.com/moby/buildkit/cache/remotecache"
15
+	"github.com/moby/buildkit/client/llb"
14 16
 	"github.com/moby/buildkit/executor"
15 17
 	"github.com/moby/buildkit/frontend"
16 18
 	gw "github.com/moby/buildkit/frontend/gateway/client"
17
-	"github.com/moby/buildkit/identity"
18 19
 	"github.com/moby/buildkit/session"
19 20
 	"github.com/moby/buildkit/solver"
21
+	"github.com/moby/buildkit/solver/pb"
22
+	"github.com/moby/buildkit/util/flightcontrol"
20 23
 	"github.com/moby/buildkit/util/tracing"
21 24
 	"github.com/moby/buildkit/worker"
22 25
 	digest "github.com/opencontainers/go-digest"
... ...
@@ -37,27 +40,28 @@ type llbBridge struct {
37 37
 	sm                        *session.Manager
38 38
 }
39 39
 
40
-func (b *llbBridge) Solve(ctx context.Context, req frontend.SolveRequest) (res *frontend.Result, err error) {
40
+func (b *llbBridge) loadResult(ctx context.Context, def *pb.Definition, cacheImports []gw.CacheOptionsEntry) (solver.CachedResult, error) {
41 41
 	w, err := b.resolveWorker()
42 42
 	if err != nil {
43 43
 		return nil, err
44 44
 	}
45
+	ent, err := loadEntitlements(b.builder)
46
+	if err != nil {
47
+		return nil, err
48
+	}
45 49
 	var cms []solver.CacheManager
46
-	for _, im := range req.CacheImports {
50
+	for _, im := range cacheImports {
51
+		cmID, err := cmKey(im)
52
+		if err != nil {
53
+			return nil, err
54
+		}
47 55
 		b.cmsMu.Lock()
48 56
 		var cm solver.CacheManager
49
-		cmId := identity.NewID()
50
-		if im.Type == "registry" {
51
-			// For compatibility with < v0.4.0
52
-			if ref := im.Attrs["ref"]; ref != "" {
53
-				cmId = ref
54
-			}
55
-		}
56
-		if prevCm, ok := b.cms[cmId]; !ok {
57
-			func(cmId string, im gw.CacheOptionsEntry) {
58
-				cm = newLazyCacheManager(cmId, func() (solver.CacheManager, error) {
57
+		if prevCm, ok := b.cms[cmID]; !ok {
58
+			func(cmID string, im gw.CacheOptionsEntry) {
59
+				cm = newLazyCacheManager(cmID, func() (solver.CacheManager, error) {
59 60
 					var cmNew solver.CacheManager
60
-					if err := inVertexContext(b.builder.Context(ctx), "importing cache manifest from "+cmId, "", func(ctx context.Context) error {
61
+					if err := inVertexContext(b.builder.Context(context.TODO()), "importing cache manifest from "+cmID, "", func(ctx context.Context) error {
61 62
 						resolveCI, ok := b.resolveCacheImporterFuncs[im.Type]
62 63
 						if !ok {
63 64
 							return errors.Errorf("unknown cache importer: %s", im.Type)
... ...
@@ -66,63 +70,70 @@ func (b *llbBridge) Solve(ctx context.Context, req frontend.SolveRequest) (res *
66 66
 						if err != nil {
67 67
 							return err
68 68
 						}
69
-						cmNew, err = ci.Resolve(ctx, desc, cmId, w)
69
+						cmNew, err = ci.Resolve(ctx, desc, cmID, w)
70 70
 						return err
71 71
 					}); err != nil {
72
-						logrus.Debugf("error while importing cache manifest from cmId=%s: %v", cmId, err)
72
+						logrus.Debugf("error while importing cache manifest from cmId=%s: %v", cmID, err)
73 73
 						return nil, err
74 74
 					}
75 75
 					return cmNew, nil
76 76
 				})
77
-			}(cmId, im)
78
-			b.cms[cmId] = cm
77
+			}(cmID, im)
78
+			b.cms[cmID] = cm
79 79
 		} else {
80 80
 			cm = prevCm
81 81
 		}
82 82
 		cms = append(cms, cm)
83 83
 		b.cmsMu.Unlock()
84 84
 	}
85
+	dpc := &detectPrunedCacheID{}
85 86
 
86
-	if req.Definition != nil && req.Definition.Def != nil && req.Frontend != "" {
87
-		return nil, errors.New("cannot solve with both Definition and Frontend specified")
87
+	edge, err := Load(def, dpc.Load, ValidateEntitlements(ent), WithCacheSources(cms), RuntimePlatforms(b.platforms), WithValidateCaps())
88
+	if err != nil {
89
+		return nil, errors.Wrap(err, "failed to load LLB")
88 90
 	}
89 91
 
90
-	if req.Definition != nil && req.Definition.Def != nil {
91
-		ent, err := loadEntitlements(b.builder)
92
-		if err != nil {
93
-			return nil, err
92
+	if len(dpc.ids) > 0 {
93
+		ids := make([]string, 0, len(dpc.ids))
94
+		for id := range dpc.ids {
95
+			ids = append(ids, id)
94 96
 		}
95
-		dpc := &detectPrunedCacheID{}
96
-
97
-		edge, err := Load(req.Definition, dpc.Load, ValidateEntitlements(ent), WithCacheSources(cms), RuntimePlatforms(b.platforms), WithValidateCaps())
98
-		if err != nil {
99
-			return nil, errors.Wrap(err, "failed to load LLB")
97
+		if err := b.eachWorker(func(w worker.Worker) error {
98
+			return w.PruneCacheMounts(ctx, ids)
99
+		}); err != nil {
100
+			return nil, err
100 101
 		}
102
+	}
101 103
 
102
-		if len(dpc.ids) > 0 {
103
-			ids := make([]string, 0, len(dpc.ids))
104
-			for id := range dpc.ids {
105
-				ids = append(ids, id)
106
-			}
107
-			if err := b.eachWorker(func(w worker.Worker) error {
108
-				return w.PruneCacheMounts(ctx, ids)
109
-			}); err != nil {
110
-				return nil, err
111
-			}
104
+	res, err := b.builder.Build(ctx, edge)
105
+	if err != nil {
106
+		return nil, err
107
+	}
108
+	wr, ok := res.Sys().(*worker.WorkerRef)
109
+	if !ok {
110
+		return nil, errors.Errorf("invalid reference for exporting: %T", res.Sys())
111
+	}
112
+	if wr.ImmutableRef != nil {
113
+		if err := wr.ImmutableRef.Finalize(ctx, false); err != nil {
114
+			return nil, err
112 115
 		}
116
+	}
117
+	return res, err
118
+}
113 119
 
114
-		ref, err := b.builder.Build(ctx, edge)
115
-		if err != nil {
116
-			return nil, errors.Wrap(err, "failed to build LLB")
117
-		}
120
+func (b *llbBridge) Solve(ctx context.Context, req frontend.SolveRequest) (res *frontend.Result, err error) {
121
+	if req.Definition != nil && req.Definition.Def != nil && req.Frontend != "" {
122
+		return nil, errors.New("cannot solve with both Definition and Frontend specified")
123
+	}
118 124
 
119
-		res = &frontend.Result{Ref: ref}
125
+	if req.Definition != nil && req.Definition.Def != nil {
126
+		res = &frontend.Result{Ref: newResultProxy(b, req)}
120 127
 	} else if req.Frontend != "" {
121 128
 		f, ok := b.frontends[req.Frontend]
122 129
 		if !ok {
123 130
 			return nil, errors.Errorf("invalid frontend: %s", req.Frontend)
124 131
 		}
125
-		res, err = f.Solve(ctx, b, req.FrontendOpt)
132
+		res, err = f.Solve(ctx, b, req.FrontendOpt, req.FrontendInputs)
126 133
 		if err != nil {
127 134
 			return nil, errors.Wrapf(err, "failed to solve with frontend %s", req.Frontend)
128 135
 		}
... ...
@@ -130,21 +141,86 @@ func (b *llbBridge) Solve(ctx context.Context, req frontend.SolveRequest) (res *
130 130
 		return &frontend.Result{}, nil
131 131
 	}
132 132
 
133
-	if err := res.EachRef(func(r solver.CachedResult) error {
134
-		wr, ok := r.Sys().(*worker.WorkerRef)
135
-		if !ok {
136
-			return errors.Errorf("invalid reference for exporting: %T", r.Sys())
133
+	return
134
+}
135
+
136
+type resultProxy struct {
137
+	cb       func(context.Context) (solver.CachedResult, error)
138
+	def      *pb.Definition
139
+	g        flightcontrol.Group
140
+	mu       sync.Mutex
141
+	released bool
142
+	v        solver.CachedResult
143
+	err      error
144
+}
145
+
146
+func newResultProxy(b *llbBridge, req frontend.SolveRequest) *resultProxy {
147
+	return &resultProxy{
148
+		def: req.Definition,
149
+		cb: func(ctx context.Context) (solver.CachedResult, error) {
150
+			return b.loadResult(ctx, req.Definition, req.CacheImports)
151
+		},
152
+	}
153
+}
154
+
155
+func (rp *resultProxy) Definition() *pb.Definition {
156
+	return rp.def
157
+}
158
+
159
+func (rp *resultProxy) Release(ctx context.Context) error {
160
+	rp.mu.Lock()
161
+	defer rp.mu.Unlock()
162
+	if rp.v != nil {
163
+		if rp.released {
164
+			logrus.Warnf("release of already released result")
137 165
 		}
138
-		if wr.ImmutableRef != nil {
139
-			if err := wr.ImmutableRef.Finalize(ctx, false); err != nil {
140
-				return err
166
+		if err := rp.v.Release(ctx); err != nil {
167
+			return err
168
+		}
169
+	}
170
+	rp.released = true
171
+	return nil
172
+}
173
+
174
+func (rp *resultProxy) Result(ctx context.Context) (solver.CachedResult, error) {
175
+	r, err := rp.g.Do(ctx, "result", func(ctx context.Context) (interface{}, error) {
176
+		rp.mu.Lock()
177
+		if rp.released {
178
+			rp.mu.Unlock()
179
+			return nil, errors.Errorf("accessing released result")
180
+		}
181
+		if rp.v != nil || rp.err != nil {
182
+			rp.mu.Unlock()
183
+			return rp.v, rp.err
184
+		}
185
+		rp.mu.Unlock()
186
+		v, err := rp.cb(ctx)
187
+		if err != nil {
188
+			select {
189
+			case <-ctx.Done():
190
+				if strings.Contains(err.Error(), context.Canceled.Error()) {
191
+					return v, err
192
+				}
193
+			default:
141 194
 			}
142 195
 		}
143
-		return nil
144
-	}); err != nil {
145
-		return nil, err
196
+		rp.mu.Lock()
197
+		if rp.released {
198
+			if v != nil {
199
+				v.Release(context.TODO())
200
+			}
201
+			rp.mu.Unlock()
202
+			return nil, errors.Errorf("evaluating released result")
203
+		}
204
+		rp.v = v
205
+		rp.err = err
206
+		rp.mu.Unlock()
207
+		return v, err
208
+	})
209
+	if r != nil {
210
+		return r.(solver.CachedResult), nil
146 211
 	}
147
-	return
212
+	return nil, err
148 213
 }
149 214
 
150 215
 func (s *llbBridge) Exec(ctx context.Context, meta executor.Meta, root cache.ImmutableRef, stdin io.ReadCloser, stdout, stderr io.WriteCloser) (err error) {
... ...
@@ -158,7 +234,7 @@ func (s *llbBridge) Exec(ctx context.Context, meta executor.Meta, root cache.Imm
158 158
 	return err
159 159
 }
160 160
 
161
-func (s *llbBridge) ResolveImageConfig(ctx context.Context, ref string, opt gw.ResolveImageConfigOpt) (dgst digest.Digest, config []byte, err error) {
161
+func (s *llbBridge) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (dgst digest.Digest, config []byte, err error) {
162 162
 	w, err := s.resolveWorker()
163 163
 	if err != nil {
164 164
 		return "", nil, err
... ...
@@ -235,3 +311,14 @@ func newLazyCacheManager(id string, fn func() (solver.CacheManager, error)) solv
235 235
 	}()
236 236
 	return lcm
237 237
 }
238
+
239
+func cmKey(im gw.CacheOptionsEntry) (string, error) {
240
+	if im.Type == "registry" && im.Attrs["ref"] != "" {
241
+		return im.Attrs["ref"], nil
242
+	}
243
+	i, err := hashstructure.Hash(im, nil)
244
+	if err != nil {
245
+		return "", err
246
+	}
247
+	return fmt.Sprintf("%s:%d", im.Type, i), nil
248
+}
... ...
@@ -26,33 +26,58 @@ func timestampToTime(ts int64) *time.Time {
26 26
 	return &tm
27 27
 }
28 28
 
29
-func mapUser(user *copy.ChownOpt, idmap *idtools.IdentityMapping) (*copy.ChownOpt, error) {
30
-	if idmap == nil || user == nil {
31
-		return user, nil
32
-	}
33
-	identity, err := idmap.ToHost(idtools.Identity{
34
-		UID: user.Uid,
35
-		GID: user.Gid,
36
-	})
37
-	if err != nil {
38
-		return nil, err
29
+func mapUserToChowner(user *copy.User, idmap *idtools.IdentityMapping) (copy.Chowner, error) {
30
+	if user == nil {
31
+		return func(old *copy.User) (*copy.User, error) {
32
+			if old == nil {
33
+				if idmap == nil {
34
+					return nil, nil
35
+				}
36
+				old = &copy.User{} // root
37
+			}
38
+			if idmap != nil {
39
+				identity, err := idmap.ToHost(idtools.Identity{
40
+					UID: old.Uid,
41
+					GID: old.Gid,
42
+				})
43
+				if err != nil {
44
+					return nil, err
45
+				}
46
+				return &copy.User{Uid: identity.UID, Gid: identity.GID}, nil
47
+			}
48
+			return old, nil
49
+		}, nil
50
+	}
51
+	u := *user
52
+	if idmap != nil {
53
+		identity, err := idmap.ToHost(idtools.Identity{
54
+			UID: user.Uid,
55
+			GID: user.Gid,
56
+		})
57
+		if err != nil {
58
+			return nil, err
59
+		}
60
+		u.Uid = identity.UID
61
+		u.Gid = identity.GID
39 62
 	}
40
-	return &copy.ChownOpt{Uid: identity.UID, Gid: identity.GID}, nil
63
+	return func(*copy.User) (*copy.User, error) {
64
+		return &u, nil
65
+	}, nil
41 66
 }
42 67
 
43
-func mkdir(ctx context.Context, d string, action pb.FileActionMkDir, user *copy.ChownOpt, idmap *idtools.IdentityMapping) error {
68
+func mkdir(ctx context.Context, d string, action pb.FileActionMkDir, user *copy.User, idmap *idtools.IdentityMapping) error {
44 69
 	p, err := fs.RootPath(d, filepath.Join(filepath.Join("/", action.Path)))
45 70
 	if err != nil {
46 71
 		return err
47 72
 	}
48 73
 
49
-	user, err = mapUser(user, idmap)
74
+	ch, err := mapUserToChowner(user, idmap)
50 75
 	if err != nil {
51 76
 		return err
52 77
 	}
53 78
 
54 79
 	if action.MakeParents {
55
-		if err := copy.MkdirAll(p, os.FileMode(action.Mode)&0777, user, timestampToTime(action.Timestamp)); err != nil {
80
+		if err := copy.MkdirAll(p, os.FileMode(action.Mode)&0777, ch, timestampToTime(action.Timestamp)); err != nil {
56 81
 			return err
57 82
 		}
58 83
 	} else {
... ...
@@ -62,7 +87,7 @@ func mkdir(ctx context.Context, d string, action pb.FileActionMkDir, user *copy.
62 62
 			}
63 63
 			return err
64 64
 		}
65
-		if err := copy.Chown(p, user); err != nil {
65
+		if err := copy.Chown(p, nil, ch); err != nil {
66 66
 			return err
67 67
 		}
68 68
 		if err := copy.Utimes(p, timestampToTime(action.Timestamp)); err != nil {
... ...
@@ -73,13 +98,13 @@ func mkdir(ctx context.Context, d string, action pb.FileActionMkDir, user *copy.
73 73
 	return nil
74 74
 }
75 75
 
76
-func mkfile(ctx context.Context, d string, action pb.FileActionMkFile, user *copy.ChownOpt, idmap *idtools.IdentityMapping) error {
76
+func mkfile(ctx context.Context, d string, action pb.FileActionMkFile, user *copy.User, idmap *idtools.IdentityMapping) error {
77 77
 	p, err := fs.RootPath(d, filepath.Join(filepath.Join("/", action.Path)))
78 78
 	if err != nil {
79 79
 		return err
80 80
 	}
81 81
 
82
-	user, err = mapUser(user, idmap)
82
+	ch, err := mapUserToChowner(user, idmap)
83 83
 	if err != nil {
84 84
 		return err
85 85
 	}
... ...
@@ -88,7 +113,7 @@ func mkfile(ctx context.Context, d string, action pb.FileActionMkFile, user *cop
88 88
 		return err
89 89
 	}
90 90
 
91
-	if err := copy.Chown(p, user); err != nil {
91
+	if err := copy.Chown(p, nil, ch); err != nil {
92 92
 		return err
93 93
 	}
94 94
 
... ...
@@ -100,13 +125,33 @@ func mkfile(ctx context.Context, d string, action pb.FileActionMkFile, user *cop
100 100
 }
101 101
 
102 102
 func rm(ctx context.Context, d string, action pb.FileActionRm) error {
103
-	p, err := fs.RootPath(d, filepath.Join(filepath.Join("/", action.Path)))
103
+	if action.AllowWildcard {
104
+		src := cleanPath(action.Path)
105
+		m, err := copy.ResolveWildcards(d, src, false)
106
+		if err != nil {
107
+			return err
108
+		}
109
+
110
+		for _, s := range m {
111
+			if err := rmPath(d, s, action.AllowNotFound); err != nil {
112
+				return err
113
+			}
114
+		}
115
+
116
+		return nil
117
+	}
118
+
119
+	return rmPath(d, action.Path, action.AllowNotFound)
120
+}
121
+
122
+func rmPath(root, src string, allowNotFound bool) error {
123
+	p, err := fs.RootPath(root, filepath.Join(filepath.Join("/", src)))
104 124
 	if err != nil {
105 125
 		return err
106 126
 	}
107 127
 
108 128
 	if err := os.RemoveAll(p); err != nil {
109
-		if os.IsNotExist(errors.Cause(err)) && action.AllowNotFound {
129
+		if os.IsNotExist(errors.Cause(err)) && allowNotFound {
110 130
 			return nil
111 131
 		}
112 132
 		return err
... ...
@@ -115,7 +160,7 @@ func rm(ctx context.Context, d string, action pb.FileActionRm) error {
115 115
 	return nil
116 116
 }
117 117
 
118
-func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *copy.ChownOpt, idmap *idtools.IdentityMapping) error {
118
+func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *copy.User, idmap *idtools.IdentityMapping) error {
119 119
 	srcPath := cleanPath(action.Src)
120 120
 	destPath := cleanPath(action.Dest)
121 121
 
... ...
@@ -134,14 +179,14 @@ func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *
134 134
 		return nil
135 135
 	}
136 136
 
137
-	u, err := mapUser(u, idmap)
137
+	ch, err := mapUserToChowner(u, idmap)
138 138
 	if err != nil {
139 139
 		return err
140 140
 	}
141 141
 
142 142
 	opt := []copy.Opt{
143 143
 		func(ci *copy.CopyInfo) {
144
-			ci.Chown = u
144
+			ci.Chown = ch
145 145
 			ci.Utime = timestampToTime(action.Timestamp)
146 146
 			if m := int(action.Mode); m != -1 {
147 147
 				ci.Mode = &m
... ...
@@ -154,7 +199,7 @@ func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *
154 154
 
155 155
 	if !action.AllowWildcard {
156 156
 		if action.AttemptUnpackDockerCompatibility {
157
-			if ok, err := unpack(ctx, src, srcPath, dest, destPath, u, timestampToTime(action.Timestamp)); err != nil {
157
+			if ok, err := unpack(ctx, src, srcPath, dest, destPath, ch, timestampToTime(action.Timestamp)); err != nil {
158 158
 				return err
159 159
 			} else if ok {
160 160
 				return nil
... ...
@@ -177,7 +222,7 @@ func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *
177 177
 
178 178
 	for _, s := range m {
179 179
 		if action.AttemptUnpackDockerCompatibility {
180
-			if ok, err := unpack(ctx, src, s, dest, destPath, u, timestampToTime(action.Timestamp)); err != nil {
180
+			if ok, err := unpack(ctx, src, s, dest, destPath, ch, timestampToTime(action.Timestamp)); err != nil {
181 181
 				return err
182 182
 			} else if ok {
183 183
 				continue
... ...
@@ -12,7 +12,7 @@ import (
12 12
 	copy "github.com/tonistiigi/fsutil/copy"
13 13
 )
14 14
 
15
-func unpack(ctx context.Context, srcRoot string, src string, destRoot string, dest string, user *copy.ChownOpt, tm *time.Time) (bool, error) {
15
+func unpack(ctx context.Context, srcRoot string, src string, destRoot string, dest string, ch copy.Chowner, tm *time.Time) (bool, error) {
16 16
 	src, err := fs.RootPath(srcRoot, src)
17 17
 	if err != nil {
18 18
 		return false, err
... ...
@@ -25,7 +25,7 @@ func unpack(ctx context.Context, srcRoot string, src string, destRoot string, de
25 25
 	if err != nil {
26 26
 		return false, err
27 27
 	}
28
-	if err := copy.MkdirAll(dest, 0755, user, tm); err != nil {
28
+	if err := copy.MkdirAll(dest, 0755, ch, tm); err != nil {
29 29
 		return false, err
30 30
 	}
31 31
 
... ...
@@ -12,11 +12,11 @@ import (
12 12
 	copy "github.com/tonistiigi/fsutil/copy"
13 13
 )
14 14
 
15
-func readUser(chopt *pb.ChownOpt, mu, mg fileoptypes.Mount) (*copy.ChownOpt, error) {
15
+func readUser(chopt *pb.ChownOpt, mu, mg fileoptypes.Mount) (*copy.User, error) {
16 16
 	if chopt == nil {
17 17
 		return nil, nil
18 18
 	}
19
-	var us copy.ChownOpt
19
+	var us copy.User
20 20
 	if chopt.User != nil {
21 21
 		switch u := chopt.User.User.(type) {
22 22
 		case *pb.UserOpt_ByName:
... ...
@@ -9,6 +9,6 @@ import (
9 9
 	copy "github.com/tonistiigi/fsutil/copy"
10 10
 )
11 11
 
12
-func readUser(chopt *pb.ChownOpt, mu, mg fileoptypes.Mount) (*copy.ChownOpt, error) {
12
+func readUser(chopt *pb.ChownOpt, mu, mg fileoptypes.Mount) (*copy.User, error) {
13 13
 	return nil, errors.New("only implemented in linux")
14 14
 }
... ...
@@ -132,5 +132,10 @@ func (b *buildOp) Exec(ctx context.Context, inputs []solver.Result) (outputs []s
132 132
 		r.Release(context.TODO())
133 133
 	}
134 134
 
135
-	return []solver.Result{newRes.Ref}, err
135
+	r, err := newRes.Ref.Result(ctx)
136
+	if err != nil {
137
+		return nil, err
138
+	}
139
+
140
+	return []solver.Result{r}, err
136 141
 }
... ...
@@ -56,7 +56,8 @@ type execOp struct {
56 56
 	platform  *pb.Platform
57 57
 	numInputs int
58 58
 
59
-	cacheMounts map[string]*cacheRefShare
59
+	cacheMounts   map[string]*cacheRefShare
60
+	cacheMountsMu sync.Mutex
60 61
 }
61 62
 
62 63
 func NewExecOp(v solver.Vertex, op *pb.Op_Exec, platform *pb.Platform, cm cache.Manager, sm *session.Manager, md *metadata.Store, exec executor.Executor, w worker.Worker) (solver.Op, error) {
... ...
@@ -221,56 +222,75 @@ func (e *execOp) getMountDeps() ([]dep, error) {
221 221
 }
222 222
 
223 223
 func (e *execOp) getRefCacheDir(ctx context.Context, ref cache.ImmutableRef, id string, m *pb.Mount, sharing pb.CacheSharingOpt) (mref cache.MutableRef, err error) {
224
+	g := &cacheRefGetter{
225
+		locker:          &e.cacheMountsMu,
226
+		cacheMounts:     e.cacheMounts,
227
+		cm:              e.cm,
228
+		md:              e.md,
229
+		globalCacheRefs: sharedCacheRefs,
230
+		name:            fmt.Sprintf("cached mount %s from exec %s", m.Dest, strings.Join(e.op.Meta.Args, " ")),
231
+	}
232
+	return g.getRefCacheDir(ctx, ref, id, sharing)
233
+}
234
+
235
+type cacheRefGetter struct {
236
+	locker          sync.Locker
237
+	cacheMounts     map[string]*cacheRefShare
238
+	cm              cache.Manager
239
+	md              *metadata.Store
240
+	globalCacheRefs *cacheRefs
241
+	name            string
242
+}
243
+
244
+func (g *cacheRefGetter) getRefCacheDir(ctx context.Context, ref cache.ImmutableRef, id string, sharing pb.CacheSharingOpt) (mref cache.MutableRef, err error) {
224 245
 	key := "cache-dir:" + id
225 246
 	if ref != nil {
226 247
 		key += ":" + ref.ID()
227 248
 	}
228
-	mu := CacheMountsLocker()
249
+	mu := g.locker
229 250
 	mu.Lock()
230 251
 	defer mu.Unlock()
231 252
 
232
-	if ref, ok := e.cacheMounts[key]; ok {
253
+	if ref, ok := g.cacheMounts[key]; ok {
233 254
 		return ref.clone(), nil
234 255
 	}
235 256
 	defer func() {
236 257
 		if err == nil {
237 258
 			share := &cacheRefShare{MutableRef: mref, refs: map[*cacheRef]struct{}{}}
238
-			e.cacheMounts[key] = share
259
+			g.cacheMounts[key] = share
239 260
 			mref = share.clone()
240 261
 		}
241 262
 	}()
242 263
 
243 264
 	switch sharing {
244 265
 	case pb.CacheSharingOpt_SHARED:
245
-		return sharedCacheRefs.get(key, func() (cache.MutableRef, error) {
246
-			return e.getRefCacheDirNoCache(ctx, key, ref, id, m, false)
266
+		return g.globalCacheRefs.get(key, func() (cache.MutableRef, error) {
267
+			return g.getRefCacheDirNoCache(ctx, key, ref, id, false)
247 268
 		})
248 269
 	case pb.CacheSharingOpt_PRIVATE:
249
-		return e.getRefCacheDirNoCache(ctx, key, ref, id, m, false)
270
+		return g.getRefCacheDirNoCache(ctx, key, ref, id, false)
250 271
 	case pb.CacheSharingOpt_LOCKED:
251
-		return e.getRefCacheDirNoCache(ctx, key, ref, id, m, true)
272
+		return g.getRefCacheDirNoCache(ctx, key, ref, id, true)
252 273
 	default:
253 274
 		return nil, errors.Errorf("invalid cache sharing option: %s", sharing.String())
254 275
 	}
255
-
256 276
 }
257 277
 
258
-func (e *execOp) getRefCacheDirNoCache(ctx context.Context, key string, ref cache.ImmutableRef, id string, m *pb.Mount, block bool) (cache.MutableRef, error) {
278
+func (g *cacheRefGetter) getRefCacheDirNoCache(ctx context.Context, key string, ref cache.ImmutableRef, id string, block bool) (cache.MutableRef, error) {
259 279
 	makeMutable := func(ref cache.ImmutableRef) (cache.MutableRef, error) {
260
-		desc := fmt.Sprintf("cached mount %s from exec %s", m.Dest, strings.Join(e.op.Meta.Args, " "))
261
-		return e.cm.New(ctx, ref, cache.WithRecordType(client.UsageRecordTypeCacheMount), cache.WithDescription(desc), cache.CachePolicyRetain)
280
+		return g.cm.New(ctx, ref, cache.WithRecordType(client.UsageRecordTypeCacheMount), cache.WithDescription(g.name), cache.CachePolicyRetain)
262 281
 	}
263 282
 
264 283
 	cacheRefsLocker.Lock(key)
265 284
 	defer cacheRefsLocker.Unlock(key)
266 285
 	for {
267
-		sis, err := e.md.Search(key)
286
+		sis, err := g.md.Search(key)
268 287
 		if err != nil {
269 288
 			return nil, err
270 289
 		}
271 290
 		locked := false
272 291
 		for _, si := range sis {
273
-			if mRef, err := e.cm.GetMutable(ctx, si.ID()); err == nil {
292
+			if mRef, err := g.cm.GetMutable(ctx, si.ID()); err == nil {
274 293
 				logrus.Debugf("reusing ref for cache dir: %s", mRef.ID())
275 294
 				return mRef, nil
276 295
 			} else if errors.Cause(err) == cache.ErrLocked {
... ...
@@ -295,7 +315,7 @@ func (e *execOp) getRefCacheDirNoCache(ctx context.Context, key string, ref cach
295 295
 		return nil, err
296 296
 	}
297 297
 
298
-	si, _ := e.md.Get(mRef.ID())
298
+	si, _ := g.md.Get(mRef.ID())
299 299
 	v, err := metadata.NewValue(key)
300 300
 	if err != nil {
301 301
 		mRef.Release(context.TODO())
... ...
@@ -525,7 +545,7 @@ func (sm *secretMountInstance) Mount() ([]mount.Mount, func() error, error) {
525 525
 	return []mount.Mount{{
526 526
 		Type:    "bind",
527 527
 		Source:  fp,
528
-		Options: []string{"ro", "rbind"},
528
+		Options: []string{"ro", "rbind", "nodev", "nosuid", "noexec"},
529 529
 	}}, cleanup, nil
530 530
 }
531 531
 
... ...
@@ -797,6 +817,9 @@ func CacheMountsLocker() sync.Locker {
797 797
 }
798 798
 
799 799
 func (r *cacheRefs) get(key string, fn func() (cache.MutableRef, error)) (cache.MutableRef, error) {
800
+	r.mu.Lock()
801
+	defer r.mu.Unlock()
802
+
800 803
 	if r.shares == nil {
801 804
 		r.shares = map[string]*cacheRefShare{}
802 805
 	}
... ...
@@ -813,7 +836,6 @@ func (r *cacheRefs) get(key string, fn func() (cache.MutableRef, error)) (cache.
813 813
 
814 814
 	share = &cacheRefShare{MutableRef: mref, main: r, key: key, refs: map[*cacheRef]struct{}{}}
815 815
 	r.shares[key] = share
816
-
817 816
 	return share.clone(), nil
818 817
 }
819 818
 
... ...
@@ -827,6 +849,9 @@ type cacheRefShare struct {
827 827
 
828 828
 func (r *cacheRefShare) clone() cache.MutableRef {
829 829
 	cacheRef := &cacheRef{cacheRefShare: r}
830
+	if cacheRefCloneHijack != nil {
831
+		cacheRefCloneHijack()
832
+	}
830 833
 	r.mu.Lock()
831 834
 	r.refs[cacheRef] = struct{}{}
832 835
 	r.mu.Unlock()
... ...
@@ -835,22 +860,30 @@ func (r *cacheRefShare) clone() cache.MutableRef {
835 835
 
836 836
 func (r *cacheRefShare) release(ctx context.Context) error {
837 837
 	if r.main != nil {
838
-		r.main.mu.Lock()
839
-		defer r.main.mu.Unlock()
840 838
 		delete(r.main.shares, r.key)
841 839
 	}
842 840
 	return r.MutableRef.Release(ctx)
843 841
 }
844 842
 
843
+var cacheRefReleaseHijack func()
844
+var cacheRefCloneHijack func()
845
+
845 846
 type cacheRef struct {
846 847
 	*cacheRefShare
847 848
 }
848 849
 
849 850
 func (r *cacheRef) Release(ctx context.Context) error {
851
+	if r.main != nil {
852
+		r.main.mu.Lock()
853
+		defer r.main.mu.Unlock()
854
+	}
850 855
 	r.mu.Lock()
851 856
 	defer r.mu.Unlock()
852 857
 	delete(r.refs, r)
853 858
 	if len(r.refs) == 0 {
859
+		if cacheRefReleaseHijack != nil {
860
+			cacheRefReleaseHijack()
861
+		}
854 862
 		return r.release(ctx)
855 863
 	}
856 864
 	return nil
... ...
@@ -22,6 +22,7 @@ import (
22 22
 	digest "github.com/opencontainers/go-digest"
23 23
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
24 24
 	"github.com/pkg/errors"
25
+	"golang.org/x/sync/errgroup"
25 26
 )
26 27
 
27 28
 const keyEntitlements = "llb.entitlements"
... ...
@@ -115,7 +116,7 @@ func (s *Solver) Solve(ctx context.Context, id string, req frontend.SolveRequest
115 115
 
116 116
 	var res *frontend.Result
117 117
 	if s.gatewayForwarder != nil && req.Definition == nil && req.Frontend == "" {
118
-		fwd := gateway.NewBridgeForwarder(ctx, s.Bridge(j), s.workerController)
118
+		fwd := gateway.NewBridgeForwarder(ctx, s.Bridge(j), s.workerController, req.FrontendInputs)
119 119
 		defer fwd.Discard()
120 120
 		if err := s.gatewayForwarder.RegisterBuild(ctx, id, fwd); err != nil {
121 121
 			return nil, err
... ...
@@ -140,12 +141,24 @@ func (s *Solver) Solve(ctx context.Context, id string, req frontend.SolveRequest
140 140
 	}
141 141
 
142 142
 	defer func() {
143
-		res.EachRef(func(ref solver.CachedResult) error {
143
+		res.EachRef(func(ref solver.ResultProxy) error {
144 144
 			go ref.Release(context.TODO())
145 145
 			return nil
146 146
 		})
147 147
 	}()
148 148
 
149
+	eg, ctx2 := errgroup.WithContext(ctx)
150
+	res.EachRef(func(ref solver.ResultProxy) error {
151
+		eg.Go(func() error {
152
+			_, err := ref.Result(ctx2)
153
+			return err
154
+		})
155
+		return nil
156
+	})
157
+	if err := eg.Wait(); err != nil {
158
+		return nil, err
159
+	}
160
+
149 161
 	var exporterResponse map[string]string
150 162
 	if e := exp.Exporter; e != nil {
151 163
 		inp := exporter.Source{
... ...
@@ -155,13 +168,17 @@ func (s *Solver) Solve(ctx context.Context, id string, req frontend.SolveRequest
155 155
 			inp.Metadata = make(map[string][]byte)
156 156
 		}
157 157
 		if res := res.Ref; res != nil {
158
-			workerRef, ok := res.Sys().(*worker.WorkerRef)
158
+			r, err := res.Result(ctx)
159
+			if err != nil {
160
+				return nil, err
161
+			}
162
+			workerRef, ok := r.Sys().(*worker.WorkerRef)
159 163
 			if !ok {
160
-				return nil, errors.Errorf("invalid reference: %T", res.Sys())
164
+				return nil, errors.Errorf("invalid reference: %T", r.Sys())
161 165
 			}
162 166
 			inp.Ref = workerRef.ImmutableRef
163 167
 
164
-			dt, err := inlineCache(ctx, exp.CacheExporter, res)
168
+			dt, err := inlineCache(ctx, exp.CacheExporter, r)
165 169
 			if err != nil {
166 170
 				return nil, err
167 171
 			}
... ...
@@ -175,13 +192,17 @@ func (s *Solver) Solve(ctx context.Context, id string, req frontend.SolveRequest
175 175
 				if res == nil {
176 176
 					m[k] = nil
177 177
 				} else {
178
-					workerRef, ok := res.Sys().(*worker.WorkerRef)
178
+					r, err := res.Result(ctx)
179
+					if err != nil {
180
+						return nil, err
181
+					}
182
+					workerRef, ok := r.Sys().(*worker.WorkerRef)
179 183
 					if !ok {
180
-						return nil, errors.Errorf("invalid reference: %T", res.Sys())
184
+						return nil, errors.Errorf("invalid reference: %T", r.Sys())
181 185
 					}
182 186
 					m[k] = workerRef.ImmutableRef
183 187
 
184
-					dt, err := inlineCache(ctx, exp.CacheExporter, res)
188
+					dt, err := inlineCache(ctx, exp.CacheExporter, r)
185 189
 					if err != nil {
186 190
 						return nil, err
187 191
 					}
... ...
@@ -205,9 +226,13 @@ func (s *Solver) Solve(ctx context.Context, id string, req frontend.SolveRequest
205 205
 	if e := exp.CacheExporter; e != nil {
206 206
 		if err := inVertexContext(j.Context(ctx), "exporting cache", "", func(ctx context.Context) error {
207 207
 			prepareDone := oneOffProgress(ctx, "preparing build cache for export")
208
-			if err := res.EachRef(func(res solver.CachedResult) error {
208
+			if err := res.EachRef(func(res solver.ResultProxy) error {
209
+				r, err := res.Result(ctx)
210
+				if err != nil {
211
+					return err
212
+				}
209 213
 				// all keys have same export chain so exporting others is not needed
210
-				_, err := res.CacheKeys()[0].Exporter.ExportTo(ctx, e, solver.CacheExportOpt{
214
+				_, err = r.CacheKeys()[0].Exporter.ExportTo(ctx, e, solver.CacheExportOpt{
211 215
 					Convert: workerRefConverter,
212 216
 					Mode:    exp.CacheExportMode,
213 217
 				})
... ...
@@ -45,7 +45,10 @@ const (
45 45
 	CapExecMountSSH                  apicaps.CapID = "exec.mount.ssh"
46 46
 	CapExecCgroupsMounted            apicaps.CapID = "exec.cgroup"
47 47
 
48
-	CapFileBase apicaps.CapID = "file.base"
48
+	CapExecMetaSecurityDeviceWhitelistV1 apicaps.CapID = "exec.meta.security.devices.v1"
49
+
50
+	CapFileBase       apicaps.CapID = "file.base"
51
+	CapFileRmWildcard apicaps.CapID = "file.rm.wildcard"
49 52
 
50 53
 	CapConstraints apicaps.CapID = "constraints"
51 54
 	CapPlatform    apicaps.CapID = "platform"
... ...
@@ -189,6 +192,12 @@ func init() {
189 189
 	})
190 190
 
191 191
 	Caps.Init(apicaps.Cap{
192
+		ID:      CapExecMetaSecurityDeviceWhitelistV1,
193
+		Enabled: true,
194
+		Status:  apicaps.CapStatusExperimental,
195
+	})
196
+
197
+	Caps.Init(apicaps.Cap{
192 198
 		ID:      CapExecMountBind,
193 199
 		Enabled: true,
194 200
 		Status:  apicaps.CapStatusExperimental,
... ...
@@ -253,6 +262,12 @@ func init() {
253 253
 	})
254 254
 
255 255
 	Caps.Init(apicaps.Cap{
256
+		ID:      CapFileRmWildcard,
257
+		Enabled: true,
258
+		Status:  apicaps.CapStatusExperimental,
259
+	})
260
+
261
+	Caps.Init(apicaps.Cap{
256 262
 		ID:      CapConstraints,
257 263
 		Enabled: true,
258 264
 		Status:  apicaps.CapStatusExperimental,
... ...
@@ -281,5 +296,4 @@ func init() {
281 281
 		Enabled: true,
282 282
 		Status:  apicaps.CapStatusExperimental,
283 283
 	})
284
-
285 284
 }
... ...
@@ -5,33 +5,48 @@ import (
5 5
 	"time"
6 6
 
7 7
 	"github.com/containerd/containerd/content"
8
+	"github.com/moby/buildkit/solver/pb"
8 9
 	digest "github.com/opencontainers/go-digest"
9 10
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
10 11
 )
11 12
 
12
-// Vertex is one node in the build graph
13
+// Vertex is a node in a build graph. It defines an interface for a
14
+// content-addressable operation and its inputs.
13 15
 type Vertex interface {
14
-	// Digest is a content-addressable vertex identifier
16
+	// Digest returns a checksum of the definition up to the vertex including
17
+	// all of its inputs.
15 18
 	Digest() digest.Digest
16
-	// Sys returns an internal value that is used to execute the vertex. Usually
17
-	// this is capured by the operation resolver method during solve.
19
+
20
+	// Sys returns an object used to resolve the executor for this vertex.
21
+	// In LLB solver, this value would be of type `llb.Op`.
18 22
 	Sys() interface{}
23
+
24
+	// Options return metadata associated with the vertex that doesn't change the
25
+	// definition or equality check of it.
19 26
 	Options() VertexOptions
20
-	// Array of edges current vertex depends on.
27
+
28
+	// Inputs returns an array of edges the vertex depends on. An input edge is
29
+	// a vertex and an index from the returned array of results from an executor
30
+	// returned by Sys(). A vertex may have zero inputs.
21 31
 	Inputs() []Edge
32
+
22 33
 	Name() string
23 34
 }
24 35
 
25
-// Index is a index value for output edge
36
+// Index is an index value for the return array of an operation. Index starts
37
+// counting from zero.
26 38
 type Index int
27 39
 
28
-// Edge is a path to a specific output of the vertex
40
+// Edge is a connection point between vertexes. An edge references a specific
41
+// output of a vertex's operation. Edges are used as inputs to other vertexes.
29 42
 type Edge struct {
30 43
 	Index  Index
31 44
 	Vertex Vertex
32 45
 }
33 46
 
34
-// VertexOptions has optional metadata for the vertex that is not contained in digest
47
+// VertexOptions define optional metadata for a vertex that doesn't change the
48
+// definition or equality check of it. These options are not contained in the
49
+// vertex digest.
35 50
 type VertexOptions struct {
36 51
 	IgnoreCache  bool
37 52
 	CacheSources []CacheManager
... ...
@@ -53,6 +68,12 @@ type CachedResult interface {
53 53
 	CacheKeys() []ExportableCacheKey
54 54
 }
55 55
 
56
+type ResultProxy interface {
57
+	Result(context.Context) (CachedResult, error)
58
+	Release(context.Context) error
59
+	Definition() *pb.Definition
60
+}
61
+
56 62
 // CacheExportMode is the type for setting cache exporting modes
57 63
 type CacheExportMode int
58 64
 
... ...
@@ -110,26 +131,44 @@ type CacheLink struct {
110 110
 	Selector digest.Digest `json:",omitempty"`
111 111
 }
112 112
 
113
-// Op is an implementation for running a vertex
113
+// Op defines how the solver can evaluate the properties of a vertex operation.
114
+// An op is executed in the worker, and is retrieved from the vertex by the
115
+// value of `vertex.Sys()`. The solver is configured with a resolve function to
116
+// convert a `vertex.Sys()` into an `Op`.
114 117
 type Op interface {
115 118
 	// CacheMap returns structure describing how the operation is cached.
116 119
 	// Currently only roots are allowed to return multiple cache maps per op.
117 120
 	CacheMap(context.Context, int) (*CacheMap, bool, error)
121
+
118 122
 	// Exec runs an operation given results from previous operations.
119 123
 	Exec(ctx context.Context, inputs []Result) (outputs []Result, err error)
120 124
 }
121 125
 
122 126
 type ResultBasedCacheFunc func(context.Context, Result) (digest.Digest, error)
123 127
 
128
+// CacheMap is a description for calculating the cache key of an operation.
124 129
 type CacheMap struct {
125
-	// Digest is a base digest for operation that needs to be combined with
126
-	// inputs cache or selectors for dependencies.
130
+	// Digest returns a checksum for the operation. The operation result can be
131
+	// cached by a checksum that combines this digest and the cache keys of the
132
+	// operation's inputs.
133
+	//
134
+	// For example, in LLB this digest is a manifest digest for OCI images, or
135
+	// commit SHA for git sources.
127 136
 	Digest digest.Digest
128
-	Deps   []struct {
129
-		// Optional digest that is merged with the cache key of the input
137
+
138
+	// Deps contain optional selectors or content-based cache functions for its
139
+	// inputs.
140
+	Deps []struct {
141
+		// Selector is a digest that is merged with the cache key of the input.
142
+		// Selectors are not merged with the result of the `ComputeDigestFunc` for
143
+		// this input.
130 144
 		Selector digest.Digest
131
-		// Optional function that returns a digest for the input based on its
132
-		// return value
145
+
146
+		// ComputeDigestFunc should return a digest for the input based on its return
147
+		// value.
148
+		//
149
+		// For example, in LLB this is invoked to calculate the cache key based on
150
+		// the checksum of file contents from input snapshots.
133 151
 		ComputeDigestFunc ResultBasedCacheFunc
134 152
 	}
135 153
 }
... ...
@@ -152,17 +191,24 @@ type CacheRecord struct {
152 152
 	key          *CacheKey
153 153
 }
154 154
 
155
-// CacheManager implements build cache backend
155
+// CacheManager determines if there is a result that matches the cache keys
156
+// generated during the build that could be reused instead of fully
157
+// reevaluating the vertex and its inputs. There can be multiple cache
158
+// managers, and specific managers can be defined per vertex using
159
+// `VertexOptions`.
156 160
 type CacheManager interface {
157 161
 	// ID is used to identify cache providers that are backed by same source
158
-	// to avoid duplicate calls to the same provider
162
+	// to avoid duplicate calls to the same provider.
159 163
 	ID() string
164
+
160 165
 	// Query searches for cache paths from one cache key to the output of a
161 166
 	// possible match.
162 167
 	Query(inp []CacheKeyWithSelector, inputIndex Index, dgst digest.Digest, outputIndex Index) ([]*CacheKey, error)
163 168
 	Records(ck *CacheKey) ([]*CacheRecord, error)
164
-	// Load pulls and returns the cached result
169
+
170
+	// Load loads a cache record into a result reference.
165 171
 	Load(ctx context.Context, rec *CacheRecord) (Result, error)
172
+
166 173
 	// Save saves a result based on a cache key
167 174
 	Save(key *CacheKey, s Result, createdAt time.Time) (*ExportableCacheKey, error)
168 175
 }
... ...
@@ -1,9 +1,17 @@
1 1
 package appdefaults
2 2
 
3
+import (
4
+	"os"
5
+	"path/filepath"
6
+)
7
+
3 8
 const (
4
-	Address   = "npipe:////./pipe/buildkitd"
5
-	Root      = ".buildstate"
6
-	ConfigDir = ""
9
+	Address = "npipe:////./pipe/buildkitd"
10
+)
11
+
12
+var (
13
+	Root      = filepath.Join(os.Getenv("ProgramData"), "buildkitd", ".buildstate")
14
+	ConfigDir = filepath.Join(os.Getenv("ProgramData"), "buildkitd")
7 15
 )
8 16
 
9 17
 func UserAddress() string {
10 18
new file mode 100644
... ...
@@ -0,0 +1,163 @@
0
+package security
1
+
2
+import (
3
+	"context"
4
+	"fmt"
5
+	"os"
6
+
7
+	"github.com/containerd/containerd/containers"
8
+	"github.com/containerd/containerd/oci"
9
+	"github.com/opencontainers/runc/libcontainer/system"
10
+	specs "github.com/opencontainers/runtime-spec/specs-go"
11
+	"github.com/pkg/errors"
12
+	"github.com/sirupsen/logrus"
13
+	"golang.org/x/sys/unix"
14
+)
15
+
16
+// WithInsecureSpec sets spec with All capability.
17
+func WithInsecureSpec() oci.SpecOpts {
18
+	return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
19
+		addCaps := []string{
20
+			"CAP_FSETID",
21
+			"CAP_KILL",
22
+			"CAP_FOWNER",
23
+			"CAP_MKNOD",
24
+			"CAP_CHOWN",
25
+			"CAP_DAC_OVERRIDE",
26
+			"CAP_NET_RAW",
27
+			"CAP_SETGID",
28
+			"CAP_SETUID",
29
+			"CAP_SETPCAP",
30
+			"CAP_SETFCAP",
31
+			"CAP_NET_BIND_SERVICE",
32
+			"CAP_SYS_CHROOT",
33
+			"CAP_AUDIT_WRITE",
34
+			"CAP_MAC_ADMIN",
35
+			"CAP_MAC_OVERRIDE",
36
+			"CAP_DAC_READ_SEARCH",
37
+			"CAP_SYS_PTRACE",
38
+			"CAP_SYS_MODULE",
39
+			"CAP_SYSLOG",
40
+			"CAP_SYS_RAWIO",
41
+			"CAP_SYS_ADMIN",
42
+			"CAP_LINUX_IMMUTABLE",
43
+			"CAP_SYS_BOOT",
44
+			"CAP_SYS_NICE",
45
+			"CAP_SYS_PACCT",
46
+			"CAP_SYS_TTY_CONFIG",
47
+			"CAP_SYS_TIME",
48
+			"CAP_WAKE_ALARM",
49
+			"CAP_AUDIT_READ",
50
+			"CAP_AUDIT_CONTROL",
51
+			"CAP_SYS_RESOURCE",
52
+			"CAP_BLOCK_SUSPEND",
53
+			"CAP_IPC_LOCK",
54
+			"CAP_IPC_OWNER",
55
+			"CAP_LEASE",
56
+			"CAP_NET_ADMIN",
57
+			"CAP_NET_BROADCAST",
58
+		}
59
+		for _, cap := range addCaps {
60
+			s.Process.Capabilities.Bounding = append(s.Process.Capabilities.Bounding, cap)
61
+			s.Process.Capabilities.Ambient = append(s.Process.Capabilities.Ambient, cap)
62
+			s.Process.Capabilities.Effective = append(s.Process.Capabilities.Effective, cap)
63
+			s.Process.Capabilities.Inheritable = append(s.Process.Capabilities.Inheritable, cap)
64
+			s.Process.Capabilities.Permitted = append(s.Process.Capabilities.Permitted, cap)
65
+		}
66
+		s.Linux.ReadonlyPaths = []string{}
67
+		s.Linux.MaskedPaths = []string{}
68
+		s.Process.ApparmorProfile = ""
69
+
70
+		s.Linux.Resources.Devices = []specs.LinuxDeviceCgroup{
71
+			{
72
+				Allow:  true,
73
+				Type:   "c",
74
+				Access: "rwm",
75
+			},
76
+			{
77
+				Allow:  true,
78
+				Type:   "b",
79
+				Access: "rwm",
80
+			},
81
+		}
82
+
83
+		if !system.RunningInUserNS() {
84
+			// Devices automatically mounted on insecure mode
85
+			s.Linux.Devices = append(s.Linux.Devices, []specs.LinuxDevice{
86
+				// Writes to this come out as printk's, reads export the buffered printk records. (dmesg)
87
+				{
88
+					Path:  "/dev/kmsg",
89
+					Type:  "c",
90
+					Major: 1,
91
+					Minor: 11,
92
+				},
93
+				// Cuse (character device in user-space)
94
+				{
95
+					Path:  "/dev/cuse",
96
+					Type:  "c",
97
+					Major: 10,
98
+					Minor: 203,
99
+				},
100
+				// Fuse (virtual filesystem in user-space)
101
+				{
102
+					Path:  "/dev/fuse",
103
+					Type:  "c",
104
+					Major: 10,
105
+					Minor: 229,
106
+				},
107
+				// Kernel-based virtual machine (hardware virtualization extensions)
108
+				{
109
+					Path:  "/dev/kvm",
110
+					Type:  "c",
111
+					Major: 10,
112
+					Minor: 232,
113
+				},
114
+				// TAP/TUN network device
115
+				{
116
+					Path:  "/dev/net/tun",
117
+					Type:  "c",
118
+					Major: 10,
119
+					Minor: 200,
120
+				},
121
+				// Loopback control device
122
+				{
123
+					Path:  "/dev/loop-control",
124
+					Type:  "c",
125
+					Major: 10,
126
+					Minor: 237,
127
+				},
128
+			}...)
129
+
130
+			loopID, err := getFreeLoopID()
131
+			if err != nil {
132
+				logrus.Debugf("failed to get next free loop device: %v", err)
133
+			}
134
+
135
+			for i := 0; i <= loopID+7; i++ {
136
+				s.Linux.Devices = append(s.Linux.Devices, specs.LinuxDevice{
137
+					Path:  fmt.Sprintf("/dev/loop%d", i),
138
+					Type:  "b",
139
+					Major: 7,
140
+					Minor: int64(i),
141
+				})
142
+			}
143
+		}
144
+
145
+		return nil
146
+	}
147
+}
148
+
149
+func getFreeLoopID() (int, error) {
150
+	fd, err := os.OpenFile("/dev/loop-control", os.O_RDWR, 0644)
151
+	if err != nil {
152
+		return 0, err
153
+	}
154
+	defer fd.Close()
155
+
156
+	const _LOOP_CTL_GET_FREE = 0x4C82
157
+	r1, _, uerr := unix.Syscall(unix.SYS_IOCTL, fd.Fd(), _LOOP_CTL_GET_FREE, 0)
158
+	if uerr == 0 {
159
+		return int(r1), nil
160
+	}
161
+	return 0, errors.Errorf("error getting free loop device: %v", uerr)
162
+}
0 163
deleted file mode 100644
... ...
@@ -1,67 +0,0 @@
1
-package entitlements
2
-
3
-import (
4
-	"context"
5
-
6
-	"github.com/containerd/containerd/containers"
7
-	"github.com/containerd/containerd/oci"
8
-	specs "github.com/opencontainers/runtime-spec/specs-go"
9
-)
10
-
11
-// WithInsecureSpec sets spec with All capability.
12
-func WithInsecureSpec() oci.SpecOpts {
13
-	return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
14
-		addCaps := []string{
15
-			"CAP_FSETID",
16
-			"CAP_KILL",
17
-			"CAP_FOWNER",
18
-			"CAP_MKNOD",
19
-			"CAP_CHOWN",
20
-			"CAP_DAC_OVERRIDE",
21
-			"CAP_NET_RAW",
22
-			"CAP_SETGID",
23
-			"CAP_SETUID",
24
-			"CAP_SETPCAP",
25
-			"CAP_SETFCAP",
26
-			"CAP_NET_BIND_SERVICE",
27
-			"CAP_SYS_CHROOT",
28
-			"CAP_AUDIT_WRITE",
29
-			"CAP_MAC_ADMIN",
30
-			"CAP_MAC_OVERRIDE",
31
-			"CAP_DAC_READ_SEARCH",
32
-			"CAP_SYS_PTRACE",
33
-			"CAP_SYS_MODULE",
34
-			"CAP_SYSLOG",
35
-			"CAP_SYS_RAWIO",
36
-			"CAP_SYS_ADMIN",
37
-			"CAP_LINUX_IMMUTABLE",
38
-			"CAP_SYS_BOOT",
39
-			"CAP_SYS_NICE",
40
-			"CAP_SYS_PACCT",
41
-			"CAP_SYS_TTY_CONFIG",
42
-			"CAP_SYS_TIME",
43
-			"CAP_WAKE_ALARM",
44
-			"CAP_AUDIT_READ",
45
-			"CAP_AUDIT_CONTROL",
46
-			"CAP_SYS_RESOURCE",
47
-			"CAP_BLOCK_SUSPEND",
48
-			"CAP_IPC_LOCK",
49
-			"CAP_IPC_OWNER",
50
-			"CAP_LEASE",
51
-			"CAP_NET_ADMIN",
52
-			"CAP_NET_BROADCAST",
53
-		}
54
-		for _, cap := range addCaps {
55
-			s.Process.Capabilities.Bounding = append(s.Process.Capabilities.Bounding, cap)
56
-			s.Process.Capabilities.Ambient = append(s.Process.Capabilities.Ambient, cap)
57
-			s.Process.Capabilities.Effective = append(s.Process.Capabilities.Effective, cap)
58
-			s.Process.Capabilities.Inheritable = append(s.Process.Capabilities.Inheritable, cap)
59
-			s.Process.Capabilities.Permitted = append(s.Process.Capabilities.Permitted, cap)
60
-		}
61
-		s.Linux.ReadonlyPaths = []string{}
62
-		s.Linux.MaskedPaths = []string{}
63
-		s.Process.ApparmorProfile = ""
64
-
65
-		return nil
66
-	}
67
-}
... ...
@@ -116,7 +116,9 @@ func newCall(fn func(ctx context.Context) (interface{}, error)) *call {
116 116
 
117 117
 func (c *call) run() {
118 118
 	defer c.closeProgressWriter()
119
-	v, err := c.fn(c.ctx)
119
+	ctx, cancel := context.WithCancel(c.ctx)
120
+	defer cancel()
121
+	v, err := c.fn(ctx)
120 122
 	c.mu.Lock()
121 123
 	c.result = v
122 124
 	c.err = err
... ...
@@ -12,6 +12,7 @@ import (
12 12
 	"github.com/containerd/containerd/platforms"
13 13
 	"github.com/containerd/containerd/reference"
14 14
 	"github.com/containerd/containerd/remotes"
15
+	"github.com/containerd/containerd/remotes/docker"
15 16
 	"github.com/moby/buildkit/util/leaseutil"
16 17
 	digest "github.com/opencontainers/go-digest"
17 18
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
... ...
@@ -152,7 +153,7 @@ func childrenConfigHandler(provider content.Provider, platform platforms.MatchCo
152 152
 			} else {
153 153
 				descs = append(descs, index.Manifests...)
154 154
 			}
155
-		case images.MediaTypeDockerSchema2Config, specs.MediaTypeImageConfig:
155
+		case images.MediaTypeDockerSchema2Config, specs.MediaTypeImageConfig, docker.LegacyConfigMediaType:
156 156
 			// childless data types.
157 157
 			return nil, nil
158 158
 		default:
... ...
@@ -7,10 +7,10 @@ import (
7 7
 	"github.com/containerd/containerd/content"
8 8
 	"github.com/moby/buildkit/cache"
9 9
 	"github.com/moby/buildkit/client"
10
+	"github.com/moby/buildkit/client/llb"
10 11
 	"github.com/moby/buildkit/executor"
11 12
 	"github.com/moby/buildkit/exporter"
12 13
 	"github.com/moby/buildkit/frontend"
13
-	gw "github.com/moby/buildkit/frontend/gateway/client"
14 14
 	"github.com/moby/buildkit/session"
15 15
 	"github.com/moby/buildkit/solver"
16 16
 	digest "github.com/opencontainers/go-digest"
... ...
@@ -26,7 +26,7 @@ type Worker interface {
26 26
 	LoadRef(id string, hidden bool) (cache.ImmutableRef, error)
27 27
 	// ResolveOp resolves Vertex.Sys() to Op implementation.
28 28
 	ResolveOp(v solver.Vertex, s frontend.FrontendLLBBridge, sm *session.Manager) (solver.Op, error)
29
-	ResolveImageConfig(ctx context.Context, ref string, opt gw.ResolveImageConfigOpt, sm *session.Manager) (digest.Digest, []byte, error)
29
+	ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt, sm *session.Manager) (digest.Digest, []byte, error)
30 30
 	// Exec is similar to executor.Exec but without []mount.Mount
31 31
 	Exec(ctx context.Context, meta executor.Meta, rootFS cache.ImmutableRef, stdin io.ReadCloser, stdout, stderr io.WriteCloser) error
32 32
 	DiskUsage(ctx context.Context, opt client.DiskUsageInfo) ([]*client.UsageInfo, error)
... ...
@@ -146,14 +146,16 @@ func (c *copier) prepareTargetDir(srcFollowed, src, destPath string, copyDirCont
146 146
 	return destPath, nil
147 147
 }
148 148
 
149
-type ChownOpt struct {
149
+type User struct {
150 150
 	Uid, Gid int
151 151
 }
152 152
 
153
+type Chowner func(*User) (*User, error)
154
+
153 155
 type XAttrErrorHandler func(dst, src, xattrKey string, err error) error
154 156
 
155 157
 type CopyInfo struct {
156
-	Chown             *ChownOpt
158
+	Chown             Chowner
157 159
 	Utime             *time.Time
158 160
 	AllowWildcards    bool
159 161
 	Mode              *int
... ...
@@ -172,7 +174,9 @@ func WithCopyInfo(ci CopyInfo) func(*CopyInfo) {
172 172
 
173 173
 func WithChown(uid, gid int) Opt {
174 174
 	return func(ci *CopyInfo) {
175
-		ci.Chown = &ChownOpt{Uid: uid, Gid: gid}
175
+		ci.Chown = func(*User) (*User, error) {
176
+			return &User{Uid: uid, Gid: gid}, nil
177
+		}
176 178
 	}
177 179
 }
178 180
 
... ...
@@ -194,14 +198,14 @@ func AllowXAttrErrors(ci *CopyInfo) {
194 194
 }
195 195
 
196 196
 type copier struct {
197
-	chown             *ChownOpt
197
+	chown             Chowner
198 198
 	utime             *time.Time
199 199
 	mode              *int
200 200
 	inodes            map[uint64]string
201 201
 	xattrErrorHandler XAttrErrorHandler
202 202
 }
203 203
 
204
-func newCopier(chown *ChownOpt, tm *time.Time, mode *int, xeh XAttrErrorHandler) *copier {
204
+func newCopier(chown Chowner, tm *time.Time, mode *int, xeh XAttrErrorHandler) *copier {
205 205
 	if xeh == nil {
206 206
 		xeh = func(dst, src, key string, err error) error {
207 207
 			return err
... ...
@@ -6,7 +6,6 @@ import (
6 6
 	"os"
7 7
 	"syscall"
8 8
 
9
-	"github.com/containerd/containerd/sys"
10 9
 	"github.com/pkg/errors"
11 10
 	"golang.org/x/sys/unix"
12 11
 )
... ...
@@ -20,11 +19,14 @@ func (c *copier) copyFileInfo(fi os.FileInfo, name string) error {
20 20
 	st := fi.Sys().(*syscall.Stat_t)
21 21
 
22 22
 	chown := c.chown
23
+	uid, gid := getUidGid(fi)
24
+	old := &User{Uid: uid, Gid: gid}
23 25
 	if chown == nil {
24
-		uid, gid := getUidGid(fi)
25
-		chown = &ChownOpt{Uid: uid, Gid: gid}
26
+		chown = func(u *User) (*User, error) {
27
+			return u, nil
28
+		}
26 29
 	}
27
-	if err := Chown(name, chown); err != nil {
30
+	if err := Chown(name, old, chown); err != nil {
28 31
 		return errors.Wrapf(err, "failed to chown %s", name)
29 32
 	}
30 33
 
... ...
@@ -43,7 +45,7 @@ func (c *copier) copyFileInfo(fi os.FileInfo, name string) error {
43 43
 			return err
44 44
 		}
45 45
 	} else {
46
-		timespec := []unix.Timespec{unix.Timespec(sys.StatAtime(st)), unix.Timespec(sys.StatMtime(st))}
46
+		timespec := []unix.Timespec{unix.Timespec(StatAtime(st)), unix.Timespec(StatMtime(st))}
47 47
 		if err := unix.UtimesNanoAt(unix.AT_FDCWD, name, timespec, unix.AT_SYMLINK_NOFOLLOW); err != nil {
48 48
 			return errors.Wrapf(err, "failed to utime %s", name)
49 49
 		}
... ...
@@ -6,7 +6,6 @@ import (
6 6
 	"os"
7 7
 	"syscall"
8 8
 
9
-	"github.com/containerd/containerd/sys"
10 9
 	"github.com/pkg/errors"
11 10
 	"golang.org/x/sys/unix"
12 11
 )
... ...
@@ -19,11 +18,14 @@ func getUidGid(fi os.FileInfo) (uid, gid int) {
19 19
 func (c *copier) copyFileInfo(fi os.FileInfo, name string) error {
20 20
 	st := fi.Sys().(*syscall.Stat_t)
21 21
 	chown := c.chown
22
+	uid, gid := getUidGid(fi)
23
+	old := &User{Uid: uid, Gid: gid}
22 24
 	if chown == nil {
23
-		uid, gid := getUidGid(fi)
24
-		chown = &ChownOpt{Uid: uid, Gid: gid}
25
+		chown = func(u *User) (*User, error) {
26
+			return u, nil
27
+		}
25 28
 	}
26
-	if err := Chown(name, chown); err != nil {
29
+	if err := Chown(name, old, chown); err != nil {
27 30
 		return errors.Wrapf(err, "failed to chown %s", name)
28 31
 	}
29 32
 
... ...
@@ -42,7 +44,7 @@ func (c *copier) copyFileInfo(fi os.FileInfo, name string) error {
42 42
 			return err
43 43
 		}
44 44
 	} else {
45
-		timespec := []unix.Timespec{unix.Timespec(sys.StatAtime(st)), unix.Timespec(sys.StatMtime(st))}
45
+		timespec := []unix.Timespec{unix.Timespec(StatAtime(st)), unix.Timespec(StatMtime(st))}
46 46
 		if err := unix.UtimesNanoAt(unix.AT_FDCWD, name, timespec, unix.AT_SYMLINK_NOFOLLOW); err != nil {
47 47
 			return errors.Wrapf(err, "failed to utime %s", name)
48 48
 		}
... ...
@@ -4,9 +4,18 @@ import (
4 4
 	"os"
5 5
 	"syscall"
6 6
 	"time"
7
+
8
+	"github.com/pkg/errors"
7 9
 )
8 10
 
9
-func Chown(p string, user *ChownOpt) error {
11
+func Chown(p string, old *User, fn Chowner) error {
12
+	if fn == nil {
13
+		return nil
14
+	}
15
+	user, err := fn(old)
16
+	if err != nil {
17
+		return errors.WithStack(err)
18
+	}
10 19
 	if user != nil {
11 20
 		if err := os.Lchown(p, user.Uid, user.Gid); err != nil {
12 21
 			return err
... ...
@@ -16,7 +25,7 @@ func Chown(p string, user *ChownOpt) error {
16 16
 }
17 17
 
18 18
 // MkdirAll is forked os.MkdirAll
19
-func MkdirAll(path string, perm os.FileMode, user *ChownOpt, tm *time.Time) error {
19
+func MkdirAll(path string, perm os.FileMode, user Chowner, tm *time.Time) error {
20 20
 	// Fast path: if we can tell whether path is a directory or file, stop with success or error.
21 21
 	dir, err := os.Stat(path)
22 22
 	if err == nil {
... ...
@@ -62,7 +71,7 @@ func MkdirAll(path string, perm os.FileMode, user *ChownOpt, tm *time.Time) erro
62 62
 		return err
63 63
 	}
64 64
 
65
-	if err := Chown(path, user); err != nil {
65
+	if err := Chown(path, nil, user); err != nil {
66 66
 		return err
67 67
 	}
68 68
 
69 69
new file mode 100644
... ...
@@ -0,0 +1,17 @@
0
+// +build darwin freebsd netbsd openbsd
1
+
2
+package fs
3
+
4
+import (
5
+	"syscall"
6
+)
7
+
8
+// Returns the last-accessed time
9
+func StatAtime(st *syscall.Stat_t) syscall.Timespec {
10
+	return st.Atimespec
11
+}
12
+
13
+// Returns the last-modified time
14
+func StatMtime(st *syscall.Stat_t) syscall.Timespec {
15
+	return st.Mtimespec
16
+}
0 17
new file mode 100644
... ...
@@ -0,0 +1,17 @@
0
+// +build dragonfly linux solaris
1
+
2
+package fs
3
+
4
+import (
5
+	"syscall"
6
+)
7
+
8
+// Returns the last-accessed time
9
+func StatAtime(st *syscall.Stat_t) syscall.Timespec {
10
+	return st.Atim
11
+}
12
+
13
+// Returns the last-modified time
14
+func StatMtime(st *syscall.Stat_t) syscall.Timespec {
15
+	return st.Mtim
16
+}
... ...
@@ -2,8 +2,6 @@ module github.com/tonistiigi/fsutil
2 2
 
3 3
 require (
4 4
 	github.com/Microsoft/go-winio v0.4.11 // indirect
5
-	github.com/Microsoft/hcsshim v0.8.5 // indirect
6
-	github.com/containerd/containerd v1.2.4
7 5
 	github.com/containerd/continuity v0.0.0-20181001140422-bd77b46c8352
8 6
 	github.com/davecgh/go-spew v1.1.1 // indirect
9 7
 	github.com/docker/docker v0.0.0-20180531152204-71cd53e4a197