diff --git a/Dockerfile b/Dockerfile index abdd0cffb0fc..200a61d3e82b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,6 +22,7 @@ ARG GO_VERSION=1.23 ARG ALPINE_VERSION=3.21 ARG XX_VERSION=1.6.1 ARG BUILDKIT_DEBUG +ARG EXPORT_BASE=alpine # minio for s3 integration tests FROM minio/minio:${MINIO_VERSION} AS minio @@ -194,12 +195,28 @@ RUN --mount=from=binaries \ FROM scratch AS release COPY --link --from=releaser /out/ / -FROM alpine:${ALPINE_VERSION} AS buildkit-export +FROM alpine:${ALPINE_VERSION} AS buildkit-export-alpine RUN apk add --no-cache fuse3 git openssh pigz xz iptables ip6tables \ && ln -s fusermount3 /usr/bin/fusermount COPY --link examples/buildctl-daemonless/buildctl-daemonless.sh /usr/bin/ VOLUME /var/lib/buildkit +FROM ubuntu:24.04 AS buildkit-export-ubuntu +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + fuse3 \ + git \ + openssh-client \ + pigz \ + xz-utils \ + iptables \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* +COPY --link examples/buildctl-daemonless/buildctl-daemonless.sh /usr/bin/ +VOLUME /var/lib/buildkit + +FROM buildkit-export-${EXPORT_BASE} AS buildkit-export + FROM gobuild-base AS containerd-build WORKDIR /go/src/github.com/containerd/containerd ARG TARGETPLATFORM diff --git a/api/types/worker.pb.go b/api/types/worker.pb.go index c4065f639176..b49b47d322ed 100644 --- a/api/types/worker.pb.go +++ b/api/types/worker.pb.go @@ -31,6 +31,7 @@ type WorkerRecord struct { Platforms []*pb.Platform `protobuf:"bytes,3,rep,name=platforms,proto3" json:"platforms,omitempty"` GCPolicy []*GCPolicy `protobuf:"bytes,4,rep,name=GCPolicy,proto3" json:"GCPolicy,omitempty"` BuildkitVersion *BuildkitVersion `protobuf:"bytes,5,opt,name=BuildkitVersion,proto3" json:"BuildkitVersion,omitempty"` + CDIDevices []*CDIDevice `protobuf:"bytes,6,rep,name=CDIDevices,proto3" json:"CDIDevices,omitempty"` } func (x *WorkerRecord) Reset() { @@ -98,6 +99,13 @@ func (x *WorkerRecord) GetBuildkitVersion() *BuildkitVersion { return nil } +func (x *WorkerRecord) GetCDIDevices() []*CDIDevice { + if x != nil { + return x.CDIDevices + } + return nil +} + type GCPolicy struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -245,6 +253,75 @@ func (x *BuildkitVersion) GetRevision() string { return "" } +type CDIDevice struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` + AutoAllow bool `protobuf:"varint,2,opt,name=AutoAllow,proto3" json:"AutoAllow,omitempty"` + Annotations map[string]string `protobuf:"bytes,3,rep,name=Annotations,proto3" json:"Annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + OnDemand bool `protobuf:"varint,4,opt,name=OnDemand,proto3" json:"OnDemand,omitempty"` +} + +func (x *CDIDevice) Reset() { + *x = CDIDevice{} + mi := &file_github_com_moby_buildkit_api_types_worker_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CDIDevice) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CDIDevice) ProtoMessage() {} + +func (x *CDIDevice) ProtoReflect() protoreflect.Message { + mi := &file_github_com_moby_buildkit_api_types_worker_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CDIDevice.ProtoReflect.Descriptor instead. +func (*CDIDevice) Descriptor() ([]byte, []int) { + return file_github_com_moby_buildkit_api_types_worker_proto_rawDescGZIP(), []int{3} +} + +func (x *CDIDevice) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *CDIDevice) GetAutoAllow() bool { + if x != nil { + return x.AutoAllow + } + return false +} + +func (x *CDIDevice) GetAnnotations() map[string]string { + if x != nil { + return x.Annotations + } + return nil +} + +func (x *CDIDevice) GetOnDemand() bool { + if x != nil { + return x.OnDemand + } + return false +} + var File_github_com_moby_buildkit_api_types_worker_proto protoreflect.FileDescriptor var file_github_com_moby_buildkit_api_types_worker_proto_rawDesc = []byte{ @@ -255,7 +332,7 @@ var file_github_com_moby_buildkit_api_types_worker_proto_rawDesc = []byte{ 0x2e, 0x76, 0x31, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x1a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x6f, 0x62, 0x79, 0x2f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2f, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x62, 0x2f, 0x6f, 0x70, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe0, 0x02, 0x0a, 0x0c, 0x57, 0x6f, 0x72, 0x6b, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa3, 0x03, 0x0a, 0x0c, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x48, 0x0a, 0x06, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x6d, 0x6f, 0x62, 0x79, 0x2e, @@ -273,34 +350,54 @@ var file_github_com_moby_buildkit_api_types_worker_proto_rawDesc = []byte{ 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6d, 0x6f, 0x62, 0x79, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0f, - 0x42, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, - 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc8, 0x01, 0x0a, 0x08, 0x47, - 0x43, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c, 0x12, 0x22, 0x0a, 0x0c, 0x6b, 0x65, 0x65, - 0x70, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0c, 0x6b, 0x65, 0x65, 0x70, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, - 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, - 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x64, 0x53, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, - 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x53, 0x70, 0x61, 0x63, 0x65, 0x12, 0x22, 0x0a, - 0x0c, 0x6d, 0x61, 0x78, 0x55, 0x73, 0x65, 0x64, 0x53, 0x70, 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x55, 0x73, 0x65, 0x64, 0x53, 0x70, 0x61, 0x63, - 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x69, 0x6e, 0x46, 0x72, 0x65, 0x65, 0x53, 0x70, 0x61, 0x63, - 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6d, 0x69, 0x6e, 0x46, 0x72, 0x65, 0x65, - 0x53, 0x70, 0x61, 0x63, 0x65, 0x22, 0x61, 0x0a, 0x0f, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, - 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x63, 0x6b, - 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, - 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, - 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x6f, 0x62, 0x79, 0x2f, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x6b, 0x69, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x3b, 0x6d, - 0x6f, 0x62, 0x79, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x5f, 0x76, 0x31, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x42, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x41, 0x0a, 0x0a, 0x43, 0x44, 0x49, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x06, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6d, 0x6f, 0x62, 0x79, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x6b, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x44, 0x49, + 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x0a, 0x43, 0x44, 0x49, 0x44, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc8, 0x01, + 0x0a, 0x08, 0x47, 0x43, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, + 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c, 0x12, 0x22, 0x0a, 0x0c, + 0x6b, 0x65, 0x65, 0x70, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0c, 0x6b, 0x65, 0x65, 0x70, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x18, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x72, 0x65, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x53, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x53, 0x70, 0x61, 0x63, 0x65, + 0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x55, 0x73, 0x65, 0x64, 0x53, 0x70, 0x61, 0x63, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x55, 0x73, 0x65, 0x64, 0x53, + 0x70, 0x61, 0x63, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x69, 0x6e, 0x46, 0x72, 0x65, 0x65, 0x53, + 0x70, 0x61, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6d, 0x69, 0x6e, 0x46, + 0x72, 0x65, 0x65, 0x53, 0x70, 0x61, 0x63, 0x65, 0x22, 0x61, 0x0a, 0x0f, 0x42, 0x75, 0x69, 0x6c, + 0x64, 0x6b, 0x69, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xef, 0x01, 0x0a, 0x09, + 0x43, 0x44, 0x49, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, + 0x09, 0x41, 0x75, 0x74, 0x6f, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x09, 0x41, 0x75, 0x74, 0x6f, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x12, 0x54, 0x0a, 0x0b, 0x41, + 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x32, 0x2e, 0x6d, 0x6f, 0x62, 0x79, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x44, 0x49, 0x44, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x4f, 0x6e, 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x4f, 0x6e, 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x1a, 0x3e, 0x0a, + 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x3b, 0x5a, + 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x6f, 0x62, 0x79, + 0x2f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x3b, 0x6d, 0x6f, 0x62, 0x79, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, + 0x74, 0x5f, 0x76, 0x31, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -315,24 +412,28 @@ func file_github_com_moby_buildkit_api_types_worker_proto_rawDescGZIP() []byte { return file_github_com_moby_buildkit_api_types_worker_proto_rawDescData } -var file_github_com_moby_buildkit_api_types_worker_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_github_com_moby_buildkit_api_types_worker_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_github_com_moby_buildkit_api_types_worker_proto_goTypes = []any{ (*WorkerRecord)(nil), // 0: moby.buildkit.v1.types.WorkerRecord (*GCPolicy)(nil), // 1: moby.buildkit.v1.types.GCPolicy (*BuildkitVersion)(nil), // 2: moby.buildkit.v1.types.BuildkitVersion - nil, // 3: moby.buildkit.v1.types.WorkerRecord.LabelsEntry - (*pb.Platform)(nil), // 4: pb.Platform + (*CDIDevice)(nil), // 3: moby.buildkit.v1.types.CDIDevice + nil, // 4: moby.buildkit.v1.types.WorkerRecord.LabelsEntry + nil, // 5: moby.buildkit.v1.types.CDIDevice.AnnotationsEntry + (*pb.Platform)(nil), // 6: pb.Platform } var file_github_com_moby_buildkit_api_types_worker_proto_depIdxs = []int32{ - 3, // 0: moby.buildkit.v1.types.WorkerRecord.Labels:type_name -> moby.buildkit.v1.types.WorkerRecord.LabelsEntry - 4, // 1: moby.buildkit.v1.types.WorkerRecord.platforms:type_name -> pb.Platform + 4, // 0: moby.buildkit.v1.types.WorkerRecord.Labels:type_name -> moby.buildkit.v1.types.WorkerRecord.LabelsEntry + 6, // 1: moby.buildkit.v1.types.WorkerRecord.platforms:type_name -> pb.Platform 1, // 2: moby.buildkit.v1.types.WorkerRecord.GCPolicy:type_name -> moby.buildkit.v1.types.GCPolicy 2, // 3: moby.buildkit.v1.types.WorkerRecord.BuildkitVersion:type_name -> moby.buildkit.v1.types.BuildkitVersion - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 3, // 4: moby.buildkit.v1.types.WorkerRecord.CDIDevices:type_name -> moby.buildkit.v1.types.CDIDevice + 5, // 5: moby.buildkit.v1.types.CDIDevice.Annotations:type_name -> moby.buildkit.v1.types.CDIDevice.AnnotationsEntry + 6, // [6:6] is the sub-list for method output_type + 6, // [6:6] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_github_com_moby_buildkit_api_types_worker_proto_init() } @@ -346,7 +447,7 @@ func file_github_com_moby_buildkit_api_types_worker_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_github_com_moby_buildkit_api_types_worker_proto_rawDesc, NumEnums: 0, - NumMessages: 4, + NumMessages: 6, NumExtensions: 0, NumServices: 0, }, diff --git a/api/types/worker.proto b/api/types/worker.proto index 51a92d6b6cc2..8f565664671d 100644 --- a/api/types/worker.proto +++ b/api/types/worker.proto @@ -12,6 +12,7 @@ message WorkerRecord { repeated pb.Platform platforms = 3; repeated GCPolicy GCPolicy = 4; BuildkitVersion BuildkitVersion = 5; + repeated CDIDevice CDIDevices = 6; } message GCPolicy { @@ -30,3 +31,10 @@ message BuildkitVersion { string version = 2; string revision = 3; } + +message CDIDevice { + string Name = 1; + bool AutoAllow = 2; + map Annotations = 3; + bool OnDemand = 4; +} \ No newline at end of file diff --git a/api/types/worker_vtproto.pb.go b/api/types/worker_vtproto.pb.go index 62ed2afe1e8f..6113a6048404 100644 --- a/api/types/worker_vtproto.pb.go +++ b/api/types/worker_vtproto.pb.go @@ -48,6 +48,13 @@ func (m *WorkerRecord) CloneVT() *WorkerRecord { } r.GCPolicy = tmpContainer } + if rhs := m.CDIDevices; rhs != nil { + tmpContainer := make([]*CDIDevice, len(rhs)) + for k, v := range rhs { + tmpContainer[k] = v.CloneVT() + } + r.CDIDevices = tmpContainer + } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) copy(r.unknownFields, m.unknownFields) @@ -104,6 +111,32 @@ func (m *BuildkitVersion) CloneMessageVT() proto.Message { return m.CloneVT() } +func (m *CDIDevice) CloneVT() *CDIDevice { + if m == nil { + return (*CDIDevice)(nil) + } + r := new(CDIDevice) + r.Name = m.Name + r.AutoAllow = m.AutoAllow + r.OnDemand = m.OnDemand + if rhs := m.Annotations; rhs != nil { + tmpContainer := make(map[string]string, len(rhs)) + for k, v := range rhs { + tmpContainer[k] = v + } + r.Annotations = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *CDIDevice) CloneMessageVT() proto.Message { + return m.CloneVT() +} + func (this *WorkerRecord) EqualVT(that *WorkerRecord) bool { if this == that { return true @@ -162,6 +195,23 @@ func (this *WorkerRecord) EqualVT(that *WorkerRecord) bool { if !this.BuildkitVersion.EqualVT(that.BuildkitVersion) { return false } + if len(this.CDIDevices) != len(that.CDIDevices) { + return false + } + for i, vx := range this.CDIDevices { + vy := that.CDIDevices[i] + if p, q := vx, vy; p != q { + if p == nil { + p = &CDIDevice{} + } + if q == nil { + q = &CDIDevice{} + } + if !p.EqualVT(q) { + return false + } + } + } return string(this.unknownFields) == string(that.unknownFields) } @@ -237,6 +287,43 @@ func (this *BuildkitVersion) EqualMessageVT(thatMsg proto.Message) bool { } return this.EqualVT(that) } +func (this *CDIDevice) EqualVT(that *CDIDevice) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if this.Name != that.Name { + return false + } + if this.AutoAllow != that.AutoAllow { + return false + } + if len(this.Annotations) != len(that.Annotations) { + return false + } + for i, vx := range this.Annotations { + vy, ok := that.Annotations[i] + if !ok { + return false + } + if vx != vy { + return false + } + } + if this.OnDemand != that.OnDemand { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *CDIDevice) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*CDIDevice) + if !ok { + return false + } + return this.EqualVT(that) +} func (m *WorkerRecord) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -267,6 +354,18 @@ func (m *WorkerRecord) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.CDIDevices) > 0 { + for iNdEx := len(m.CDIDevices) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.CDIDevices[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x32 + } + } if m.BuildkitVersion != nil { size, err := m.BuildkitVersion.MarshalToSizedBufferVT(dAtA[:i]) if err != nil { @@ -456,6 +555,85 @@ func (m *BuildkitVersion) MarshalToSizedBufferVT(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *CDIDevice) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CDIDevice) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *CDIDevice) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.OnDemand { + i-- + if m.OnDemand { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x20 + } + if len(m.Annotations) > 0 { + for k := range m.Annotations { + v := m.Annotations[k] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(k) + copy(dAtA[i:], k) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = protohelpers.EncodeVarint(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x1a + } + } + if m.AutoAllow { + i-- + if m.AutoAllow { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *WorkerRecord) SizeVT() (n int) { if m == nil { return 0 @@ -490,6 +668,12 @@ func (m *WorkerRecord) SizeVT() (n int) { l = m.BuildkitVersion.SizeVT() n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } + if len(m.CDIDevices) > 0 { + for _, e := range m.CDIDevices { + l = e.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } n += len(m.unknownFields) return n } @@ -547,6 +731,34 @@ func (m *BuildkitVersion) SizeVT() (n int) { return n } +func (m *CDIDevice) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.AutoAllow { + n += 2 + } + if len(m.Annotations) > 0 { + for k, v := range m.Annotations { + _ = k + _ = v + mapEntrySize := 1 + len(k) + protohelpers.SizeOfVarint(uint64(len(k))) + 1 + len(v) + protohelpers.SizeOfVarint(uint64(len(v))) + n += mapEntrySize + 1 + protohelpers.SizeOfVarint(uint64(mapEntrySize)) + } + } + if m.OnDemand { + n += 2 + } + n += len(m.unknownFields) + return n +} + func (m *WorkerRecord) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -839,6 +1051,40 @@ func (m *WorkerRecord) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CDIDevices", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CDIDevices = append(m.CDIDevices, &CDIDevice{}) + if err := m.CDIDevices[len(m.CDIDevices)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) @@ -1187,3 +1433,253 @@ func (m *BuildkitVersion) UnmarshalVT(dAtA []byte) error { } return nil } +func (m *CDIDevice) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CDIDevice: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CDIDevice: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AutoAllow", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.AutoAllow = bool(v != 0) + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Annotations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Annotations == nil { + m.Annotations = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return protohelpers.ErrInvalidLength + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return protohelpers.ErrInvalidLength + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return protohelpers.ErrInvalidLength + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return protohelpers.ErrInvalidLength + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Annotations[mapkey] = mapvalue + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field OnDemand", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.OnDemand = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/client/client_test.go b/client/client_test.go index fd183f2fb9c0..497e8ebd084e 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -274,6 +274,13 @@ func testIntegration(t *testing.T, funcs ...func(t *testing.T, sb integration.Sa "dns": bridgeDNSNetwork, }), ) + + integration.Run(t, integration.TestFuncs( + testCDI, + testCDIFirst, + testCDIWildcard, + testCDIClass, + ), mirrors) } func newContainerd(cdAddress string) (*ctd.Client, error) { @@ -7436,8 +7443,8 @@ func testMergeOp(t *testing.T, sb integration.Sandbox) { File(llb.Mkfile("bar/D", 0644, []byte("D"))). File(llb.Mkfile("bar/E", 0755, nil)). File(llb.Mkfile("qaz", 0644, nil)), - // /foo from stateE is not here because it is deleted in stateB, which is part of a submerge of mergeD ) + // /foo from stateE is not here because it is deleted in stateB, which is part of a submerge of mergeD } func testMergeOpCacheInline(t *testing.T, sb integration.Sandbox) { @@ -10986,3 +10993,257 @@ func (w warningsListOutput) String() string { } return b.String() } + +func testCDI(t *testing.T, sb integration.Sandbox) { + if sb.Rootless() { + t.SkipNow() + } + + integration.SkipOnPlatform(t, "windows") + c, err := New(sb.Context(), sb.Address()) + require.NoError(t, err) + defer c.Close() + + require.NoError(t, os.WriteFile(filepath.Join(sb.CDISpecDir(), "vendor1-device.yaml"), []byte(` +cdiVersion: "0.3.0" +kind: "vendor1.com/device" +devices: +- name: foo + containerEdits: + env: + - FOO=injected +`), 0600)) + require.NoError(t, os.WriteFile(filepath.Join(sb.CDISpecDir(), "vendor2-device.yaml"), []byte(` +cdiVersion: "0.3.0" +kind: "vendor2.com/device" +devices: +- name: bar + containerEdits: + env: + - BAR=injected +`), 0600)) + + busybox := llb.Image("busybox:latest") + st := llb.Scratch() + + run := func(cmd string, ro ...llb.RunOption) { + st = busybox.Run(append(ro, llb.Shlex(cmd), llb.Dir("/wd"))...).AddMount("/wd", st) + } + + run(`sh -c 'env|sort | tee foo.env'`, llb.AddCDIDevice(llb.CDIDeviceName("vendor1.com/device=foo"))) + run(`sh -c 'env|sort | tee bar.env'`, llb.AddCDIDevice(llb.CDIDeviceName("vendor2.com/device=bar"))) + run(`ls`, llb.AddCDIDevice(llb.CDIDeviceName("vendor3.com/device=baz"), llb.CDIDeviceOptional)) + + def, err := st.Marshal(sb.Context()) + require.NoError(t, err) + + destDir := t.TempDir() + + _, err = c.Solve(sb.Context(), def, SolveOpt{ + Exports: []ExportEntry{ + { + Type: ExporterLocal, + OutputDir: destDir, + }, + }, + }, nil) + require.NoError(t, err) + + dt, err := os.ReadFile(filepath.Join(destDir, "foo.env")) + require.NoError(t, err) + require.Contains(t, strings.TrimSpace(string(dt)), `FOO=injected`) + + dt2, err := os.ReadFile(filepath.Join(destDir, "bar.env")) + require.NoError(t, err) + require.Contains(t, strings.TrimSpace(string(dt2)), `BAR=injected`) +} + +func testCDIFirst(t *testing.T, sb integration.Sandbox) { + if sb.Rootless() { + t.SkipNow() + } + + integration.SkipOnPlatform(t, "windows") + c, err := New(sb.Context(), sb.Address()) + require.NoError(t, err) + defer c.Close() + + require.NoError(t, os.WriteFile(filepath.Join(sb.CDISpecDir(), "vendor1-device.yaml"), []byte(` +cdiVersion: "0.3.0" +kind: "vendor1.com/device" +devices: +- name: foo + containerEdits: + env: + - FOO=injected +- name: bar + containerEdits: + env: + - BAR=injected +- name: baz + containerEdits: + env: + - BAZ=injected +- name: qux + containerEdits: + env: + - QUX=injected +`), 0600)) + + busybox := llb.Image("busybox:latest") + st := llb.Scratch() + + run := func(cmd string, ro ...llb.RunOption) { + st = busybox.Run(append(ro, llb.Shlex(cmd), llb.Dir("/wd"))...).AddMount("/wd", st) + } + + run(`sh -c 'env|sort | tee first.env'`, llb.AddCDIDevice(llb.CDIDeviceName("vendor1.com/device"))) + + def, err := st.Marshal(sb.Context()) + require.NoError(t, err) + + destDir := t.TempDir() + + _, err = c.Solve(sb.Context(), def, SolveOpt{ + Exports: []ExportEntry{ + { + Type: ExporterLocal, + OutputDir: destDir, + }, + }, + }, nil) + require.NoError(t, err) + + dt, err := os.ReadFile(filepath.Join(destDir, "first.env")) + require.NoError(t, err) + require.Contains(t, strings.TrimSpace(string(dt)), `BAR=injected`) + require.NotContains(t, strings.TrimSpace(string(dt)), `FOO=injected`) + require.NotContains(t, strings.TrimSpace(string(dt)), `BAZ=injected`) + require.NotContains(t, strings.TrimSpace(string(dt)), `QUX=injected`) +} + +func testCDIWildcard(t *testing.T, sb integration.Sandbox) { + if sb.Rootless() { + t.SkipNow() + } + + integration.SkipOnPlatform(t, "windows") + c, err := New(sb.Context(), sb.Address()) + require.NoError(t, err) + defer c.Close() + + require.NoError(t, os.WriteFile(filepath.Join(sb.CDISpecDir(), "vendor1-device.yaml"), []byte(` +cdiVersion: "0.3.0" +kind: "vendor1.com/device" +devices: +- name: foo + containerEdits: + env: + - FOO=injected +- name: bar + containerEdits: + env: + - BAR=injected +`), 0600)) + + busybox := llb.Image("busybox:latest") + st := llb.Scratch() + + run := func(cmd string, ro ...llb.RunOption) { + st = busybox.Run(append(ro, llb.Shlex(cmd), llb.Dir("/wd"))...).AddMount("/wd", st) + } + + run(`sh -c 'env|sort | tee all.env'`, llb.AddCDIDevice(llb.CDIDeviceName("vendor1.com/device=*"))) + + def, err := st.Marshal(sb.Context()) + require.NoError(t, err) + + destDir := t.TempDir() + + _, err = c.Solve(sb.Context(), def, SolveOpt{ + Exports: []ExportEntry{ + { + Type: ExporterLocal, + OutputDir: destDir, + }, + }, + }, nil) + require.NoError(t, err) + + dt, err := os.ReadFile(filepath.Join(destDir, "all.env")) + require.NoError(t, err) + require.Contains(t, strings.TrimSpace(string(dt)), `FOO=injected`) + require.Contains(t, strings.TrimSpace(string(dt)), `BAR=injected`) +} + +func testCDIClass(t *testing.T, sb integration.Sandbox) { + if sb.Rootless() { + t.SkipNow() + } + + integration.SkipOnPlatform(t, "windows") + c, err := New(sb.Context(), sb.Address()) + require.NoError(t, err) + defer c.Close() + + require.NoError(t, os.WriteFile(filepath.Join(sb.CDISpecDir(), "vendor1-device.yaml"), []byte(` +cdiVersion: "0.6.0" +kind: "vendor1.com/device" +annotations: + foo.bar.baz: FOO +devices: +- name: foo + annotations: + org.mobyproject.buildkit.device.class: class1 + containerEdits: + env: + - FOO=injected +- name: bar + annotations: + org.mobyproject.buildkit.device.class: class1 + containerEdits: + env: + - BAR=injected +- name: baz + annotations: + org.mobyproject.buildkit.device.class: class2 + containerEdits: + env: + - BAZ=injected +- name: qux + containerEdits: + env: + - QUX=injected +`), 0600)) + + busybox := llb.Image("busybox:latest") + st := llb.Scratch() + + run := func(cmd string, ro ...llb.RunOption) { + st = busybox.Run(append(ro, llb.Shlex(cmd), llb.Dir("/wd"))...).AddMount("/wd", st) + } + + run(`sh -c 'env|sort | tee class.env'`, llb.AddCDIDevice(llb.CDIDeviceName("vendor1.com/device=class1"))) + + def, err := st.Marshal(sb.Context()) + require.NoError(t, err) + + destDir := t.TempDir() + + _, err = c.Solve(sb.Context(), def, SolveOpt{ + Exports: []ExportEntry{ + { + Type: ExporterLocal, + OutputDir: destDir, + }, + }, + }, nil) + require.NoError(t, err) + + dt, err := os.ReadFile(filepath.Join(destDir, "class.env")) + require.NoError(t, err) + require.Contains(t, strings.TrimSpace(string(dt)), `FOO=injected`) + require.Contains(t, strings.TrimSpace(string(dt)), `BAR=injected`) + require.NotContains(t, strings.TrimSpace(string(dt)), `BAZ=injected`) + require.NotContains(t, strings.TrimSpace(string(dt)), `QUX=injected`) +} diff --git a/client/info.go b/client/info.go index d5bdbcec8968..a637ffae1627 100644 --- a/client/info.go +++ b/client/info.go @@ -18,6 +18,13 @@ type BuildkitVersion struct { Revision string `json:"revision"` } +type CDIDevice struct { + Name string `json:"name"` + AutoAllow bool `json:"autoAllow"` + Annotations map[string]string `json:"annotations"` + OnDemand bool `json:"onDemand"` +} + func (c *Client) Info(ctx context.Context) (*Info, error) { res, err := c.ControlClient().Info(ctx, &controlapi.InfoRequest{}) if err != nil { @@ -38,3 +45,16 @@ func fromAPIBuildkitVersion(in *apitypes.BuildkitVersion) BuildkitVersion { Revision: in.Revision, } } + +func fromAPICDIDevices(in []*apitypes.CDIDevice) []CDIDevice { + var out []CDIDevice + for _, d := range in { + out = append(out, CDIDevice{ + Name: d.Name, + AutoAllow: d.AutoAllow, + Annotations: d.Annotations, + OnDemand: d.OnDemand, + }) + } + return out +} diff --git a/client/llb/exec.go b/client/llb/exec.go index a10fb94a26d6..ba66e7332c2d 100644 --- a/client/llb/exec.go +++ b/client/llb/exec.go @@ -60,6 +60,7 @@ type ExecOp struct { isValidated bool secrets []SecretInfo ssh []SSHInfo + cdiDevices []CDIDeviceInfo } func (e *ExecOp) AddMount(target string, source Output, opt ...MountOption) Output { @@ -266,6 +267,7 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, [] Network: network, Security: security, } + if network != NetModeSandbox { addCap(&e.constraints, pb.CapExecMetaNetwork) } @@ -321,6 +323,18 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, [] addCap(&e.constraints, pb.CapExecMountSSH) } + if len(e.cdiDevices) > 0 { + addCap(&e.constraints, pb.CapExecMetaCDI) + cd := make([]*pb.CDIDevice, len(e.cdiDevices)) + for i, d := range e.cdiDevices { + cd[i] = &pb.CDIDevice{ + Name: d.Name, + Optional: d.Optional, + } + } + peo.CdiDevices = cd + } + if e.constraints.Platform == nil { p, err := getPlatform(e.base)(ctx, c) if err != nil { @@ -624,6 +638,41 @@ func AddUlimit(name UlimitName, soft int64, hard int64) RunOption { }) } +func AddCDIDevice(opts ...CDIDeviceOption) RunOption { + return runOptionFunc(func(ei *ExecInfo) { + c := &CDIDeviceInfo{} + for _, opt := range opts { + opt.SetCDIDeviceOption(c) + } + ei.CDIDevices = append(ei.CDIDevices, *c) + }) +} + +type CDIDeviceOption interface { + SetCDIDeviceOption(*CDIDeviceInfo) +} + +type cdiDeviceOptionFunc func(*CDIDeviceInfo) + +func (fn cdiDeviceOptionFunc) SetCDIDeviceOption(ci *CDIDeviceInfo) { + fn(ci) +} + +func CDIDeviceName(name string) CDIDeviceOption { + return cdiDeviceOptionFunc(func(ci *CDIDeviceInfo) { + ci.Name = name + }) +} + +var CDIDeviceOptional = cdiDeviceOptionFunc(func(ci *CDIDeviceInfo) { + ci.Optional = true +}) + +type CDIDeviceInfo struct { + Name string + Optional bool +} + func ValidExitCodes(codes ...int) RunOption { return runOptionFunc(func(ei *ExecInfo) { ei.State = validExitCodes(codes...)(ei.State) @@ -815,6 +864,7 @@ type ExecInfo struct { ProxyEnv *ProxyEnv Secrets []SecretInfo SSH []SSHInfo + CDIDevices []CDIDeviceInfo } type MountInfo struct { diff --git a/client/llb/state.go b/client/llb/state.go index b52aaa244339..5743a31e389a 100644 --- a/client/llb/state.go +++ b/client/llb/state.go @@ -295,6 +295,7 @@ func (s State) Run(ro ...RunOption) ExecState { } exec.secrets = ei.Secrets exec.ssh = ei.SSH + exec.cdiDevices = ei.CDIDevices return ExecState{ State: s.WithOutput(exec.Output()), diff --git a/client/workers.go b/client/workers.go index 10b0cbf85992..a55581751499 100644 --- a/client/workers.go +++ b/client/workers.go @@ -18,6 +18,7 @@ type WorkerInfo struct { Platforms []ocispecs.Platform `json:"platforms"` GCPolicy []PruneInfo `json:"gcPolicy"` BuildkitVersion BuildkitVersion `json:"buildkitVersion"` + CDIDevices []CDIDevice `json:"cdiDevices"` } // ListWorkers lists all active workers @@ -42,6 +43,7 @@ func (c *Client) ListWorkers(ctx context.Context, opts ...ListWorkersOption) ([] Platforms: pb.ToSpecPlatforms(w.Platforms), GCPolicy: fromAPIGCPolicy(w.GCPolicy), BuildkitVersion: fromAPIBuildkitVersion(w.BuildkitVersion), + CDIDevices: fromAPICDIDevices(w.CDIDevices), }) } diff --git a/cmd/buildctl/debug/workers.go b/cmd/buildctl/debug/workers.go index 42703e971f9d..58fc6ad10d1a 100644 --- a/cmd/buildctl/debug/workers.go +++ b/cmd/buildctl/debug/workers.go @@ -82,6 +82,23 @@ func printWorkersVerbose(tw *tabwriter.Writer, winfo []*client.WorkerInfo) { v := wi.Labels[k] fmt.Fprintf(tw, "\t%s:\t%s\n", k, v) } + if len(wi.CDIDevices) > 0 { + fmt.Fprint(tw, "Devices:\n") + for _, d := range wi.CDIDevices { + fmt.Fprintf(tw, "\tName:\t%s\n", d.Name) + if d.OnDemand { + fmt.Fprintf(tw, "\tOnDemand:\t%v\n", d.OnDemand) + } else { + fmt.Fprintf(tw, "\tAutoAllow:\t%v\n", d.AutoAllow) + } + + for _, k := range sortedKeys(d.Annotations) { + v := d.Annotations[k] + fmt.Fprintf(tw, "\t\t%s:\t%s\n", k, v) + } + } + fmt.Fprint(tw, "\n") + } for i, rule := range wi.GCPolicy { fmt.Fprintf(tw, "GC Policy rule#%d:\n", i) fmt.Fprintf(tw, "\tAll:\t%v\n", rule.All) diff --git a/cmd/buildkitd/config/config.go b/cmd/buildkitd/config/config.go index 480f0450a443..381effcdc9b7 100644 --- a/cmd/buildkitd/config/config.go +++ b/cmd/buildkitd/config/config.go @@ -23,6 +23,8 @@ type Config struct { OTEL OTELConfig `toml:"otel"` + CDI CDIConfig `toml:"cdi"` + Workers struct { OCI OCIConfig `toml:"oci"` Containerd ContainerdConfig `toml:"containerd"` @@ -74,6 +76,11 @@ type OTELConfig struct { SocketPath string `toml:"socketPath"` } +type CDIConfig struct { + Disabled *bool `toml:"disabled"` + SpecDirs []string `toml:"specDirs"` +} + type GCConfig struct { GC *bool `toml:"gc"` // Deprecated: use GCReservedSpace instead diff --git a/cmd/buildkitd/devices_nvidia.go b/cmd/buildkitd/devices_nvidia.go new file mode 100644 index 000000000000..3980cb6b0a8d --- /dev/null +++ b/cmd/buildkitd/devices_nvidia.go @@ -0,0 +1,8 @@ +//go:build nvidia +// +build nvidia + +package main + +import ( + _ "github.com/moby/buildkit/contrib/cdisetup/nvidia" +) diff --git a/cmd/buildkitd/devices_venus.go b/cmd/buildkitd/devices_venus.go new file mode 100644 index 000000000000..caca3b919bb5 --- /dev/null +++ b/cmd/buildkitd/devices_venus.go @@ -0,0 +1,8 @@ +//go:build venus +// +build venus + +package main + +import ( + _ "github.com/moby/buildkit/contrib/cdisetup/venus" +) diff --git a/cmd/buildkitd/main.go b/cmd/buildkitd/main.go index cdfe9a948a0e..77d48620f7a8 100644 --- a/cmd/buildkitd/main.go +++ b/cmd/buildkitd/main.go @@ -74,6 +74,7 @@ import ( "google.golang.org/grpc/health" healthv1 "google.golang.org/grpc/health/grpc_health_v1" "google.golang.org/grpc/reflection" + "tags.cncf.io/container-device-interface/pkg/cdi" ) func init() { @@ -216,6 +217,14 @@ func main() { Name: "otel-socket-path", Usage: "OTEL collector trace socket path", }, + cli.BoolFlag{ + Name: "cdi-disabled", + Usage: "disables support of the Container Device Interface (CDI)", + }, + cli.StringSliceFlag{ + Name: "cdi-spec-dir", + Usage: "list of directories to scan for CDI spec files", + }, ) app.Flags = append(app.Flags, appFlags...) app.Flags = append(app.Flags, serviceFlags()...) @@ -537,6 +546,10 @@ func setDefaultConfig(cfg *config.Config) { if cfg.OTEL.SocketPath == "" { cfg.OTEL.SocketPath = appdefaults.TraceSocketPath(isRootlessConfig()) } + + if len(cfg.CDI.SpecDirs) == 0 { + cfg.CDI.SpecDirs = appdefaults.CDISpecDirs + } } // isRootlessConfig is true if we should be using the rootless config @@ -619,6 +632,14 @@ func applyMainFlags(c *cli.Context, cfg *config.Config) error { cfg.OTEL.SocketPath = c.String("otel-socket-path") } + if c.IsSet("cdi-disabled") { + cdiDisabled := c.Bool("cdi-disabled") + cfg.CDI.Disabled = &cdiDisabled + } + if c.IsSet("cdi-spec-dir") { + cfg.CDI.SpecDirs = c.StringSlice("cdi-spec-dir") + } + applyPlatformFlags(c) return nil @@ -1024,3 +1045,30 @@ func newMeterProvider(ctx context.Context) (*sdkmetric.MeterProvider, error) { } return sdkmetric.NewMeterProvider(opts...), nil } + +// getCDIManager returns a new CDI registry with disabled auto-refresh. +func getCDIManager(disabled *bool, specDirs []string) (*cdi.Cache, error) { + if disabled != nil && *disabled { + return nil, nil + } + if len(specDirs) == 0 { + return nil, errors.New("No CDI specification directories specified") + } + cdiCache, err := func() (*cdi.Cache, error) { + cdiCache, err := cdi.NewCache( + cdi.WithSpecDirs(specDirs...), + cdi.WithAutoRefresh(false), + ) + if err != nil { + return nil, err + } + if err := cdiCache.Refresh(); err != nil { + return nil, err + } + return cdiCache, nil + }() + if err != nil { + return nil, errors.Wrapf(err, "CDI registry initialization failure") + } + return cdiCache, nil +} diff --git a/cmd/buildkitd/main_containerd_worker.go b/cmd/buildkitd/main_containerd_worker.go index d07bc99ec2bf..13694a48d5bc 100644 --- a/cmd/buildkitd/main_containerd_worker.go +++ b/cmd/buildkitd/main_containerd_worker.go @@ -12,6 +12,7 @@ import ( ctd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/defaults" "github.com/moby/buildkit/cmd/buildkitd/config" + "github.com/moby/buildkit/solver/llbsolver/cdidevices" "github.com/moby/buildkit/util/bklog" "github.com/moby/buildkit/util/disk" "github.com/moby/buildkit/util/network/cniprovider" @@ -282,6 +283,11 @@ func containerdWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([ dns := getDNSConfig(common.config.DNS) + cdiManager, err := getCDIManager(common.config.CDI.Disabled, common.config.CDI.SpecDirs) + if err != nil { + return nil, err + } + nc := netproviders.Opt{ Mode: common.config.Workers.Containerd.NetworkConfig.Mode, CNI: cniprovider.Opt{ @@ -339,6 +345,7 @@ func containerdWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([ ParallelismSem: parallelismSem, TraceSocket: common.traceSocket, Runtime: runtime, + CDIManager: cdidevices.NewManager(cdiManager), } opt, err := containerd.NewWorkerOpt(workerOpts, ctd.WithTimeout(60*time.Second)) diff --git a/cmd/buildkitd/main_oci_worker.go b/cmd/buildkitd/main_oci_worker.go index a8a27ed4f61a..ee1ed9eb962f 100644 --- a/cmd/buildkitd/main_oci_worker.go +++ b/cmd/buildkitd/main_oci_worker.go @@ -298,6 +298,11 @@ func ociWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker dns := getDNSConfig(common.config.DNS) + cdiManager, err := getCDIManager(common.config.CDI.Disabled, common.config.CDI.SpecDirs) + if err != nil { + return nil, err + } + nc := netproviders.Opt{ Mode: common.config.Workers.OCI.NetworkConfig.Mode, CNI: cniprovider.Opt{ @@ -315,7 +320,7 @@ func ociWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker parallelismSem = semaphore.NewWeighted(int64(cfg.MaxParallelism)) } - opt, err := runc.NewWorkerOpt(common.config.Root, snFactory, cfg.Rootless, processMode, cfg.Labels, idmapping, nc, dns, cfg.Binary, cfg.ApparmorProfile, cfg.SELinux, parallelismSem, common.traceSocket, cfg.DefaultCgroupParent) + opt, err := runc.NewWorkerOpt(common.config.Root, snFactory, cfg.Rootless, processMode, cfg.Labels, idmapping, nc, dns, cfg.Binary, cfg.ApparmorProfile, cfg.SELinux, parallelismSem, common.traceSocket, cfg.DefaultCgroupParent, cdiManager) if err != nil { return nil, err } diff --git a/contrib/cdisetup/nvidia/log.go b/contrib/cdisetup/nvidia/log.go new file mode 100644 index 000000000000..554b86358195 --- /dev/null +++ b/contrib/cdisetup/nvidia/log.go @@ -0,0 +1,37 @@ +package nvidia + +import ( + "log" + + "github.com/moby/buildkit/client" + "github.com/moby/buildkit/identity" + "github.com/moby/buildkit/util/progress" + digest "github.com/opencontainers/go-digest" +) + +func newStream(pw progress.Writer, stream int, dgst digest.Digest) *streamWriter { + return &streamWriter{ + pw: pw, + stream: stream, + dgst: dgst, + } +} + +type streamWriter struct { + pw progress.Writer + stream int + dgst digest.Digest +} + +func (sw *streamWriter) Write(dt []byte) (int, error) { + err := sw.pw.Write(identity.NewID(), client.VertexLog{ + Vertex: sw.dgst, + Stream: sw.stream, + Data: dt, + }) + if err != nil { + return 0, err + } + log.Printf("%d %s", sw.stream, dt) + return len(dt), nil +} diff --git a/contrib/cdisetup/nvidia/nvidia.go b/contrib/cdisetup/nvidia/nvidia.go new file mode 100644 index 000000000000..9a4d32bab84c --- /dev/null +++ b/contrib/cdisetup/nvidia/nvidia.go @@ -0,0 +1,304 @@ +package nvidia + +import ( + "bufio" + "bytes" + "context" + "fmt" + "net/http" + "os" + "os/exec" + "path/filepath" + "regexp" + "runtime" + "strings" + "time" + + "github.com/moby/buildkit/client" + "github.com/moby/buildkit/identity" + "github.com/moby/buildkit/solver/llbsolver/cdidevices" + "github.com/moby/buildkit/util/progress" + digest "github.com/opencontainers/go-digest" + "github.com/pkg/errors" +) + +// This is example of experimental on-demand setup of a CDI devices. +// This code is not currently shipping with BuildKit and will probably change. + +const ( + cdiKind = "nvidia.com/gpu" + defaultVersion = "570.0" +) + +func init() { + cdidevices.Register(cdiKind, &setup{}) +} + +type setup struct{} + +var _ cdidevices.Setup = &setup{} + +func (s *setup) Validate() error { + _, err := readVersion() + if err == nil { + return nil + } + b, err := hasNvidiaDevices() + if err != nil { + return err + } + if !b { + return errors.Errorf("no NVIDIA devices found") + } + return nil +} + +func newVertex(ctx context.Context, name string) (progress.Writer, digest.Digest, func(error)) { + pw, _, ctx := progress.NewFromContext(ctx) + start := time.Now() + id := identity.NewID() + v := &client.Vertex{ + Name: name, + Digest: digest.FromBytes([]byte(id)), + } + v.Started = &start + v.Completed = nil + v.Cached = false + pw.Write(id, *v) + + pw2, _, _ := progress.NewFromContext(ctx, progress.WithMetadata("vertex", v.Digest)) + + return pw2, v.Digest, func(err error) { + pw2.Close() + stop := time.Now() + v.Completed = &stop + if err != nil { + v.Error = err.Error() + } else { + v.Error = "" + } + pw.Write(id, *v) + pw.Close() + } +} + +func (s *setup) Run(ctx context.Context) (err error) { + pw, dgst, closeProgress := newVertex(ctx, fmt.Sprintf("preparing device %s", cdiKind)) + defer func() { + closeProgress(err) + }() + + isDistro, _ := isDebianOrUbuntu() + if !isDistro { + return errors.Errorf("NVIDIA setup is currently only supported on Debian/Ubuntu") + } + + var needsDriver bool + + if _, err := os.Stat("/proc/driver/nvidia"); err != nil { + needsDriver = true + } + + var arch string + switch runtime.GOARCH { + case "amd64": + arch = "x86_64" + case "arm64": + arch = "sbsa" + // for non-sbsa could use https://nvidia.github.io/libnvidia-container/stable/deb + } + + if arch == "" { + return errors.Errorf("unsupported architecture: %s", runtime.GOARCH) + } + + if needsDriver { + pw.Write(identity.NewID(), client.VertexWarning{ + Vertex: dgst, + Short: []byte("NVIDIA Drivers not found. Installing prebuilt drivers is not recommended"), + }) + } + + version, err := readVersion() + if err != nil && !needsDriver { + return errors.Wrapf(err, "failed to read NVIDIA driver version") + } + if version == "" { + version = defaultVersion + } + v1, _, ok := strings.Cut(version, ".") + if !ok { + return errors.Errorf("failed to parse NVIDIA driver version %q", version) + } + + if err := run(ctx, []string{"apt-get", "update"}, pw, dgst); err != nil { + return err + } + + if err := run(ctx, []string{"apt-get", "install", "-y", "gpg"}, pw, dgst); err != nil { + return err + } + + const aptDistro = "ubuntu2404" + aptURL := "https://developer.download.nvidia.com/compute/cuda/repos/" + aptDistro + "/" + arch + "/" + + keyTarget := "/usr/share/keyrings/nvidia-cuda-keyring.gpg" + + if _, err := os.Stat(keyTarget); err != nil { + fmt.Fprintf(newStream(pw, 2, dgst), "Downloading NVIDIA GPG key\n") + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, aptURL+"3bf863cc.pub", nil) + if err != nil { + return errors.Wrapf(err, "failed to create request for NVIDIA GPG key") + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return errors.Wrapf(err, "failed to download NVIDIA GPG key") + } + + cmd := exec.CommandContext(ctx, "gpg", "--dearmor", "-o", keyTarget) + cmd.Stdin = resp.Body + cmd.Stderr = newStream(pw, 2, dgst) + if err := cmd.Run(); err != nil { + return errors.Wrapf(err, "failed to install NVIDIA GPG key") + } + resp.Body.Close() + } + + if err := os.WriteFile("/etc/apt/sources.list.d/nvidia-cuda.list", []byte("deb [signed-by="+keyTarget+"] "+aptURL+" /"), 0644); err != nil { + return errors.Wrapf(err, "failed to add NVIDIA apt repo") + } + + if err := run(ctx, []string{"apt-get", "update"}, pw, dgst); err != nil { + return err + } + + if needsDriver { + // this pretty much never works, is it even worth having? + // better approach could be to try to create another chroot/container that is built with same kernel packages as the host + // could nvidia-headless-no-dkms- be reusable + if err := run(ctx, []string{"apt-get", "install", "-y", "nvidia-driver-" + v1}, pw, dgst); err != nil { + return err + } + _, err := os.Stat("/proc/driver/nvidia") + if err != nil { + return errors.Wrapf(err, "failed to install NVIDIA kernel module. Please install NVIDIA drivers manually") + } + } + + if err := run(ctx, []string{"apt-get", "install", "-y", "--no-install-recommends", + "libnvidia-compute-" + v1, + "libnvidia-extra-" + v1, + "libnvidia-gl-" + v1, + "nvidia-utils-" + v1, + "nvidia-container-toolkit-base", + }, pw, dgst); err != nil { + return err + } + + if err := os.MkdirAll("/etc/cdi", 0700); err != nil { + return errors.Wrapf(err, "failed to create /etc/cdi") + } + + buf := &bytes.Buffer{} + + cmd := exec.CommandContext(ctx, "nvidia-ctk", "cdi", "generate") + cmd.Stdout = buf + cmd.Stderr = newStream(pw, 2, dgst) + if err := cmd.Run(); err != nil { + return errors.Wrapf(err, "failed to generate CDI spec") + } + + if len(buf.Bytes()) == 0 { + return errors.Errorf("nvidia-ctk output is empty") + } + + if err := os.WriteFile("/etc/cdi/nvidia.yaml", buf.Bytes(), 0644); err != nil { + return errors.Wrapf(err, "failed to write /etc/cdi/nvidia.yaml") + } + + return nil +} + +func run(ctx context.Context, args []string, pw progress.Writer, dgst digest.Digest) error { + fmt.Fprintf(newStream(pw, 2, dgst), "> %s\n", strings.Join(args, " ")) + cmd := exec.CommandContext(ctx, args[0], args[1:]...) //nolint:gosec + cmd.Stderr = newStream(pw, 2, dgst) + cmd.Stdout = newStream(pw, 1, dgst) + return cmd.Run() +} + +func readVersion() (string, error) { + dt, err := os.ReadFile("/proc/driver/nvidia/version") + if err != nil { + return "", err + } + return parseVersion(string(dt)) +} + +func parseVersion(dt string) (string, error) { + re := regexp.MustCompile(`NVIDIA .* Kernel Module(?:[\s\w\d]+)?\s+(\d+\.\d+)`) + matches := re.FindStringSubmatch(dt) + if len(matches) < 2 { + return "", errors.Errorf("could not parse NVIDIA driver version") + } + return matches[1], nil +} + +func hasNvidiaDevices() (bool, error) { + const pciDevicesPath = "/sys/bus/pci/devices" + const nvidiaVendorID = "0x10de" + + found := false + + dirs, err := os.ReadDir(pciDevicesPath) + if err != nil { + return false, err + } + + for _, dir := range dirs { + data, err := os.ReadFile(filepath.Join(pciDevicesPath, dir.Name(), "vendor")) + if err != nil { + continue + } + if strings.TrimSpace(string(data)) == nvidiaVendorID { + found = true + break + } + } + + return found, nil +} + +func getOSID() (string, error) { + file, err := os.Open("/etc/os-release") + if err != nil { + return "", err + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + if strings.HasPrefix(line, "ID=") { + id := strings.TrimPrefix(line, "ID=") + return strings.Trim(id, `"`), nil // Remove potential quotes + } + } + + if err := scanner.Err(); err != nil { + return "", err + } + + return "", errors.Errorf("ID not found in /etc/os-release") +} + +func isDebianOrUbuntu() (bool, error) { + id, err := getOSID() + if err != nil { + return false, err + } + + return id == "debian" || id == "ubuntu", nil +} diff --git a/contrib/cdisetup/nvidia/nvidia_test.go b/contrib/cdisetup/nvidia/nvidia_test.go new file mode 100644 index 000000000000..c80d1140dfd6 --- /dev/null +++ b/contrib/cdisetup/nvidia/nvidia_test.go @@ -0,0 +1,20 @@ +package nvidia + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseVersion(t *testing.T) { + in := `NVRM version: NVIDIA UNIX aarch64 Kernel Module 550.120 Fri Sep 13 11:01:10 UTC 2024` + out, err := parseVersion(in) + require.NoError(t, err) + require.Equal(t, "550.120", out) + + in = `NVRM version: NVIDIA UNIX Open Kernel Module for aarch64 550.144.03 Release Build (dvs-builder@U16-I2-C01-12-4) Mon Dec 30 17:33:24 UTC 2024 +GCC version: gcc version 12.3.0 (Ubuntu 12.3.0-1ubuntu1~22.04)` + out, err = parseVersion(in) + require.NoError(t, err) + require.Equal(t, "550.144", out) +} diff --git a/contrib/cdisetup/venus/venus_unix.go b/contrib/cdisetup/venus/venus_unix.go new file mode 100644 index 000000000000..2398511a27b8 --- /dev/null +++ b/contrib/cdisetup/venus/venus_unix.go @@ -0,0 +1,88 @@ +//go:build !windows + +package venus + +import ( + "bytes" + "context" + "os" + "strings" + + "github.com/moby/buildkit/solver/llbsolver/cdidevices" + "github.com/pkg/errors" + "golang.org/x/sys/unix" +) + +const ( + cdiKind = "docker.com/gpu" +) + +func init() { + cdidevices.Register(cdiKind, &setup{}) +} + +type setup struct { +} + +var _ cdidevices.Setup = &setup{} + +func (s *setup) Validate() error { + kVersion, err := getKernelVersion() + if err != nil { + return errors.Wrap(err, "failed to get kernel version") + } + if !strings.Contains(kVersion, "linuxkit") { + return errors.Errorf("%s currently requires a linuxkit kernel", cdiKind) + } + + _, err = os.Stat("/dev/dri") + if err != nil { + if os.IsNotExist(err) { + return errors.Errorf("no DRI device found, make you use Docker VMM Hypervisor") + } + return errors.Wrap(err, "failed to check DRI device") + } + + for _, dev := range []string{"renderD128", "card0"} { + if _, err := os.Stat("/dev/dri/" + dev); err != nil { + return errors.Wrapf(err, "failed to check DRI device %s", dev) + } + } + return nil +} + +func (s *setup) Run(ctx context.Context) error { + if err := s.Validate(); err != nil { + return err + } + + const dt = `cdiVersion: "0.6.0" +kind: "docker.com/gpu" +annotations: + cdi.device.name: "Virtio-GPU Venus (Docker Desktop)" +devices: +- name: venus + containerEdits: + deviceNodes: + - path: /dev/dri/card0 + - path: /dev/dri/renderD128 +` + + if err := os.MkdirAll("/etc/cdi", 0700); err != nil { + return errors.Wrap(err, "failed to create /etc/cdi") + } + + if err := os.WriteFile("/etc/cdi/venus.yaml", []byte(dt), 0600); err != nil { + return errors.Wrap(err, "failed to write /etc/cdi/venus.yaml") + } + + return nil +} + +func getKernelVersion() (string, error) { + var uts unix.Utsname + if err := unix.Uname(&uts); err != nil { + return "", err + } + return string(uts.Release[:bytes.IndexByte(uts.Release[:], 0)]), nil +} diff --git a/contrib/cdisetup/venus/venus_windows.go b/contrib/cdisetup/venus/venus_windows.go new file mode 100644 index 000000000000..4ecdb3fc1456 --- /dev/null +++ b/contrib/cdisetup/venus/venus_windows.go @@ -0,0 +1 @@ +package venus diff --git a/control/control.go b/control/control.go index 592775d9d015..ca50913190b9 100644 --- a/control/control.go +++ b/control/control.go @@ -33,6 +33,7 @@ import ( "github.com/moby/buildkit/solver" "github.com/moby/buildkit/solver/bboltcachestorage" "github.com/moby/buildkit/solver/llbsolver" + "github.com/moby/buildkit/solver/llbsolver/cdidevices" "github.com/moby/buildkit/solver/llbsolver/proc" "github.com/moby/buildkit/solver/pb" "github.com/moby/buildkit/util/bklog" @@ -586,6 +587,7 @@ func (c *Controller) ListWorkers(ctx context.Context, r *controlapi.ListWorkersR Platforms: pb.PlatformsFromSpec(w.Platforms(true)), GCPolicy: toPBGCPolicy(w.GCPolicy()), BuildkitVersion: toPBBuildkitVersion(w.BuildkitVersion()), + CDIDevices: toPBCDIDevices(w.CDIManager()), }) } return resp, nil @@ -684,6 +686,23 @@ func toPBBuildkitVersion(in client.BuildkitVersion) *apitypes.BuildkitVersion { } } +func toPBCDIDevices(manager *cdidevices.Manager) []*apitypes.CDIDevice { + if manager == nil { + return nil + } + devs := manager.ListDevices() + out := make([]*apitypes.CDIDevice, 0, len(devs)) + for _, dev := range devs { + out = append(out, &apitypes.CDIDevice{ + Name: dev.Name, + AutoAllow: true, // TODO + Annotations: dev.Annotations, + OnDemand: dev.OnDemand, + }) + } + return out +} + func findDuplicateCacheOptions(cacheOpts []*controlapi.CacheOptionsEntry) ([]*controlapi.CacheOptionsEntry, error) { seen := map[string]*controlapi.CacheOptionsEntry{} duplicate := map[string]struct{}{} diff --git a/docs/buildkitd.toml.md b/docs/buildkitd.toml.md index 71061c626868..ec314b9f08ba 100644 --- a/docs/buildkitd.toml.md +++ b/docs/buildkitd.toml.md @@ -46,6 +46,13 @@ insecure-entitlements = [ "network.host", "security.insecure" ] # OTEL collector trace socket path socketPath = "/run/buildkit/otel-grpc.sock" +[cdi] + # Disables support of the Container Device Interface (CDI). + disabled = true + # List of directories to scan for CDI spec files. For more details about CDI + # specification, please refer to https://github.com/cncf-tags/container-device-interface/blob/main/SPEC.md#cdi-json-specification + specDirs = ["/etc/cdi", "/var/run/cdi", "/etc/buildkit/cdi"] + # config for build history API that stores information about completed build commands [history] # maxAge is the maximum age of history entries to keep, in seconds. diff --git a/docs/cdi.md b/docs/cdi.md new file mode 100644 index 000000000000..ff1668115f4c --- /dev/null +++ b/docs/cdi.md @@ -0,0 +1,114 @@ +# CDI + +[CDI (Container Device Interface)](https://github.com/cncf-tags/container-device-interface/blob/main/SPEC.md) +provides a standard mechanism for device vendors to describe what is required +to provide access to a specific resource such as a GPU beyond a simple device +name. + +Since BuildKit 0.20.0, you can access devices using the CDI interface. This +allows you to use devices like GPUs in your builds. + +## Usage + +To use CDI with BuildKit, you need to create the [CDI configuration file](https://github.com/cncf-tags/container-device-interface/blob/main/SPEC.md#cdi-json-specification) +for your device (either JSON or YAML) and put it in one of the following +locations: +* `/etc/cdi` +* `/var/run/cdi` +* `/etc/buildkit/cdi` + +> [!NOTE] +> Location can be changed by setting the `specDirs` option in the `cdi` section +> of the [`buildkitd.toml` configuration file](buildkitd.toml.md). + +Let's create a simple CDI configuration file that injects an environment +variable into the build environment and write it to `/etc/cdi/foo.yml`: + +```yaml +cdiVersion: "0.6.0" +kind: "vendor1.com/device" +devices: +- name: foo + containerEdits: + env: + - FOO=injected +``` + +Start BuildKit and check the list of available devices for the default worker: + +```bash +buildctl debug workers -v + +Platforms: linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6 +BuildKit: github.com/moby/buildkit v0.19.0-rc3-72-gb89ee491b.m b89ee491bc1c40b8533f098dab18e414c8b70885.m +Labels: + org.mobyproject.buildkit.worker.executor: oci + org.mobyproject.buildkit.worker.hostname: cc39352c87dd + org.mobyproject.buildkit.worker.network: host + org.mobyproject.buildkit.worker.oci.process-mode: sandbox + org.mobyproject.buildkit.worker.selinux.enabled: false + org.mobyproject.buildkit.worker.snapshotter: overlayfs +Devices: + Name: vendor1.com/device=foo + AutoAllow: true + +GC Policy rule#0: + All: false + Filters: type==source.local,type==exec.cachemount,type==source.git.checkout + Keep duration: 48h0m0s + Maximum used space: 512MB +GC Policy rule#1: + All: false + Keep duration: 1440h0m0s + Reserved space: 10GB + Minimum free space: 202GB + Maximum used space: 100GB +GC Policy rule#2: + All: false + Reserved space: 10GB + Minimum free space: 202GB + Maximum used space: 100GB +GC Policy rule#3: + All: true + Reserved space: 10GB + Minimum free space: 202GB + Maximum used space: 100GB +``` + +Now let's create a Dockerfile to use this device: + +```dockerfile +FROM busybox +RUN --device=vendor1.com/device=foo \ + env|grep FOO +``` + +And check if the environment variable is injected during build: + +```bash +buildctl build --frontend=dockerfile.v0 --no-cache --local context=. --local dockerfile=. +#1 [internal] load build definition from Dockerfile +#1 transferring dockerfile: 99B done +#1 DONE 0.0s + +#2 [internal] load metadata for docker.io/library/busybox:latest +#2 ... + +#3 [auth] library/busybox:pull token for registry-1.docker.io +#3 DONE 0.0s + +#2 [internal] load metadata for docker.io/library/busybox:latest +#2 DONE 0.8s + +#4 [internal] load .dockerignore +#4 transferring context: 2B done +#4 DONE 0.0s + +#5 [1/2] FROM docker.io/library/busybox:latest@sha256:a5d0ce49aa801d475da48f8cb163c354ab95cab073cd3c138bd458fc8257fbf1 +#5 resolve docker.io/library/busybox:latest@sha256:a5d0ce49aa801d475da48f8cb163c354ab95cab073cd3c138bd458fc8257fbf1 0.0s done +#5 CACHED + +#6 [2/2] RUN --device=vendor1.com/device=foo env|grep FOO +#6 0.062 FOO=injected +#6 DONE 0.1s +``` diff --git a/executor/containerdexecutor/executor.go b/executor/containerdexecutor/executor.go index 4022de0a6dfe..366959f01492 100644 --- a/executor/containerdexecutor/executor.go +++ b/executor/containerdexecutor/executor.go @@ -22,6 +22,7 @@ import ( resourcestypes "github.com/moby/buildkit/executor/resources/types" gatewayapi "github.com/moby/buildkit/frontend/gateway/pb" "github.com/moby/buildkit/identity" + "github.com/moby/buildkit/solver/llbsolver/cdidevices" "github.com/moby/buildkit/solver/pb" "github.com/moby/buildkit/util/network" "github.com/pkg/errors" @@ -40,6 +41,7 @@ type containerdExecutor struct { traceSocket string rootless bool runtime *RuntimeInfo + cdiManager *cdidevices.Manager } // OnCreateRuntimer provides an alternative to OCI hooks for applying network @@ -72,6 +74,7 @@ type ExecutorOptions struct { TraceSocket string Rootless bool Runtime *RuntimeInfo + CDIManager *cdidevices.Manager } // New creates a new executor backed by connection to containerd API @@ -92,6 +95,7 @@ func New(executorOpts ExecutorOptions) executor.Executor { traceSocket: executorOpts.TraceSocket, rootless: executorOpts.Rootless, runtime: executorOpts.Runtime, + cdiManager: executorOpts.CDIManager, } } diff --git a/executor/containerdexecutor/executor_unix.go b/executor/containerdexecutor/executor_unix.go index 10b6fababecf..2233909cdff5 100644 --- a/executor/containerdexecutor/executor_unix.go +++ b/executor/containerdexecutor/executor_unix.go @@ -145,7 +145,7 @@ func (w *containerdExecutor) createOCISpec(ctx context.Context, id, resolvConf, } processMode := oci.ProcessSandbox // FIXME(AkihiroSuda) - spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, w.cgroupParent, processMode, nil, w.apparmorProfile, w.selinux, w.traceSocket, opts...) + spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, w.cgroupParent, processMode, nil, w.apparmorProfile, w.selinux, w.traceSocket, w.cdiManager, opts...) if err != nil { releaseAll() return nil, nil, err diff --git a/executor/containerdexecutor/executor_windows.go b/executor/containerdexecutor/executor_windows.go index 14f0cf444caa..b09114deb432 100644 --- a/executor/containerdexecutor/executor_windows.go +++ b/executor/containerdexecutor/executor_windows.go @@ -88,7 +88,7 @@ func (w *containerdExecutor) createOCISpec(ctx context.Context, id, _, _ string, } processMode := oci.ProcessSandbox // FIXME(AkihiroSuda) - spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, "", "", namespace, "", processMode, nil, "", false, w.traceSocket, opts...) + spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, "", "", namespace, "", processMode, nil, "", false, w.traceSocket, nil, opts...) if err != nil { releaseAll() return nil, nil, err diff --git a/executor/executor.go b/executor/executor.go index 9902392084b6..d35e18af6513 100644 --- a/executor/executor.go +++ b/executor/executor.go @@ -22,6 +22,7 @@ type Meta struct { ReadonlyRootFS bool ExtraHosts []HostIP Ulimit []*pb.Ulimit + CDIDevices []*pb.CDIDevice CgroupParent string NetMode pb.NetMode SecurityMode pb.SecurityMode diff --git a/executor/oci/spec.go b/executor/oci/spec.go index fe0b03c4a1c1..a6034e6ed000 100644 --- a/executor/oci/spec.go +++ b/executor/oci/spec.go @@ -17,6 +17,7 @@ import ( "github.com/mitchellh/hashstructure/v2" "github.com/moby/buildkit/executor" "github.com/moby/buildkit/snapshot" + "github.com/moby/buildkit/solver/llbsolver/cdidevices" "github.com/moby/buildkit/util/network" rootlessmountopts "github.com/moby/buildkit/util/rootless/mountopts" traceexec "github.com/moby/buildkit/util/tracing/exec" @@ -59,7 +60,7 @@ func (pm ProcessMode) String() string { // GenerateSpec generates spec using containerd functionality. // opts are ignored for s.Process, s.Hostname, and s.Mounts . -func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, namespace network.Namespace, cgroupParent string, processMode ProcessMode, idmap *idtools.IdentityMapping, apparmorProfile string, selinuxB bool, tracingSocket string, opts ...oci.SpecOpts) (*specs.Spec, func(), error) { +func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, namespace network.Namespace, cgroupParent string, processMode ProcessMode, idmap *idtools.IdentityMapping, apparmorProfile string, selinuxB bool, tracingSocket string, cdiManager *cdidevices.Manager, opts ...oci.SpecOpts) (*specs.Spec, func(), error) { c := &containers.Container{ ID: id, } @@ -129,6 +130,14 @@ func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mou oci.WithHostname(hostname), ) + if cdiManager != nil { + if cdiOpts, err := generateCDIOpts(cdiManager, meta.CDIDevices); err == nil { + opts = append(opts, cdiOpts...) + } else { + return nil, nil, err + } + } + s, err := oci.GenerateSpec(ctx, nil, c, opts...) if err != nil { return nil, nil, errors.WithStack(err) diff --git a/executor/oci/spec_darwin.go b/executor/oci/spec_darwin.go index c2658ecb9e6b..ae609a216bce 100644 --- a/executor/oci/spec_darwin.go +++ b/executor/oci/spec_darwin.go @@ -5,6 +5,7 @@ import ( "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/continuity/fs" "github.com/docker/docker/pkg/idtools" + "github.com/moby/buildkit/solver/llbsolver/cdidevices" "github.com/moby/buildkit/solver/pb" "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" @@ -62,3 +63,10 @@ func sub(m mount.Mount, subPath string) (mount.Mount, func() error, error) { m.Source = src return m, func() error { return nil }, nil } + +func generateCDIOpts(_ *cdidevices.Manager, devices []*pb.CDIDevice) ([]oci.SpecOpts, error) { + if len(devices) == 0 { + return nil, nil + } + return nil, errors.New("no support for CDI on Darwin") +} diff --git a/executor/oci/spec_freebsd.go b/executor/oci/spec_freebsd.go index 73cbe7ec7917..d1456a8eca53 100644 --- a/executor/oci/spec_freebsd.go +++ b/executor/oci/spec_freebsd.go @@ -5,6 +5,7 @@ import ( "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/continuity/fs" "github.com/docker/docker/pkg/idtools" + "github.com/moby/buildkit/solver/llbsolver/cdidevices" "github.com/moby/buildkit/solver/pb" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" @@ -70,3 +71,10 @@ func sub(m mount.Mount, subPath string) (mount.Mount, func() error, error) { m.Source = src return m, func() error { return nil }, nil } + +func generateCDIOpts(_ *cdidevices.Manager, devices []*pb.CDIDevice) ([]oci.SpecOpts, error) { + if len(devices) == 0 { + return nil, nil + } + return nil, errors.New("no support for CDI on FreeBSD") +} diff --git a/executor/oci/spec_linux.go b/executor/oci/spec_linux.go index 9ee59fc85a7d..7b437c28b8b0 100644 --- a/executor/oci/spec_linux.go +++ b/executor/oci/spec_linux.go @@ -17,7 +17,9 @@ import ( "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/profiles/seccomp" "github.com/moby/buildkit/snapshot" + "github.com/moby/buildkit/solver/llbsolver/cdidevices" "github.com/moby/buildkit/solver/pb" + "github.com/moby/buildkit/util/bklog" "github.com/moby/buildkit/util/entitlements/security" specs "github.com/opencontainers/runtime-spec/specs-go" selinux "github.com/opencontainers/selinux/go-selinux" @@ -148,6 +150,34 @@ func generateRlimitOpts(ulimits []*pb.Ulimit) ([]oci.SpecOpts, error) { }, nil } +// genereateCDIOptions creates the OCI runtime spec options for injecting CDI +// devices. +func generateCDIOpts(manager *cdidevices.Manager, devs []*pb.CDIDevice) ([]oci.SpecOpts, error) { + if len(devs) == 0 { + return nil, nil + } + + withCDIDevices := func(devs []*pb.CDIDevice) oci.SpecOpts { + return func(ctx context.Context, _ oci.Client, c *containers.Container, s *specs.Spec) error { + if err := manager.Refresh(); err != nil { + bklog.G(ctx).Warnf("CDI registry refresh failed: %v", err) + } + if err := manager.InjectDevices(s, devs...); err != nil { + return errors.Wrapf(err, "CDI device injection failed") + } + // One crucial thing to keep in mind is that CDI device injection + // might add OCI Spec environment variables, hooks, and mounts as + // well. Therefore, it is important that none of the corresponding + // OCI Spec fields are reset up in the call stack once we return. + return nil + } + } + + return []oci.SpecOpts{ + withCDIDevices(devs), + }, nil +} + // withDefaultProfile sets the default seccomp profile to the spec. // Note: must follow the setting of process capabilities func withDefaultProfile() oci.SpecOpts { diff --git a/executor/oci/spec_windows.go b/executor/oci/spec_windows.go index d3059c3034f4..f21b28ed8bbe 100644 --- a/executor/oci/spec_windows.go +++ b/executor/oci/spec_windows.go @@ -14,6 +14,7 @@ import ( "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/continuity/fs" "github.com/docker/docker/pkg/idtools" + "github.com/moby/buildkit/solver/llbsolver/cdidevices" "github.com/moby/buildkit/solver/pb" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" @@ -110,3 +111,11 @@ func sub(m mount.Mount, subPath string) (mount.Mount, func() error, error) { m.Source = src return m, func() error { return nil }, nil } + +func generateCDIOpts(_ *cdidevices.Manager, devices []*pb.CDIDevice) ([]oci.SpecOpts, error) { + if len(devices) == 0 { + return nil, nil + } + // https://github.com/cncf-tags/container-device-interface/issues/28 + return nil, errors.New("no support for CDI on Windows") +} diff --git a/executor/runcexecutor/executor.go b/executor/runcexecutor/executor.go index f284c90cd1dc..1ca978bbb75f 100644 --- a/executor/runcexecutor/executor.go +++ b/executor/runcexecutor/executor.go @@ -30,6 +30,7 @@ import ( resourcestypes "github.com/moby/buildkit/executor/resources/types" gatewayapi "github.com/moby/buildkit/frontend/gateway/pb" "github.com/moby/buildkit/identity" + "github.com/moby/buildkit/solver/llbsolver/cdidevices" "github.com/moby/buildkit/solver/pb" "github.com/moby/buildkit/util/network" rootlessspecconv "github.com/moby/buildkit/util/rootless/specconv" @@ -57,6 +58,7 @@ type Opt struct { SELinux bool TracingSocket string ResourceMonitor *resources.Monitor + CDIManager *cdidevices.Manager } var defaultCommandCandidates = []string{"buildkit-runc", "runc"} @@ -78,6 +80,7 @@ type runcExecutor struct { selinux bool tracingSocket string resmon *resources.Monitor + cdiManager *cdidevices.Manager } func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Executor, error) { @@ -144,6 +147,7 @@ func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Ex selinux: opt.SELinux, tracingSocket: opt.TracingSocket, resmon: opt.ResourceMonitor, + cdiManager: opt.CDIManager, } return w, nil } @@ -267,7 +271,7 @@ func (w *runcExecutor) Run(ctx context.Context, id string, root executor.Mount, } } - spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, w.cgroupParent, w.processMode, w.idmap, w.apparmorProfile, w.selinux, w.tracingSocket, opts...) + spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, w.cgroupParent, w.processMode, w.idmap, w.apparmorProfile, w.selinux, w.tracingSocket, w.cdiManager, opts...) if err != nil { return nil, err } diff --git a/frontend/dockerfile/dockerfile2llb/convert.go b/frontend/dockerfile/dockerfile2llb/convert.go index c084e3991ee3..8c99d8babc48 100644 --- a/frontend/dockerfile/dockerfile2llb/convert.go +++ b/frontend/dockerfile/dockerfile2llb/convert.go @@ -724,6 +724,7 @@ func toDispatchState(ctx context.Context, dt []byte, opt ConvertOpt) (*dispatchS extraHosts: opt.ExtraHosts, shmSize: opt.ShmSize, ulimit: opt.Ulimits, + devices: opt.Devices, cgroupParent: opt.CgroupParent, llbCaps: opt.LLBCaps, sourceMap: opt.SourceMap, @@ -859,6 +860,7 @@ type dispatchOpt struct { extraHosts []llb.HostIP shmSize int64 ulimit []*pb.Ulimit + devices []*pb.CDIDevice cgroupParent string llbCaps *apicaps.CapSet sourceMap *llb.SourceMap @@ -1303,6 +1305,23 @@ func dispatchRun(d *dispatchState, c *instructions.RunCommand, proxy *llb.ProxyE } } + if dopt.llbCaps != nil && dopt.llbCaps.Supports(pb.CapExecMetaCDI) == nil { + for _, device := range dopt.devices { + deviceOpts := []llb.CDIDeviceOption{ + llb.CDIDeviceName(device.Name), + } + if device.Optional { + deviceOpts = append(deviceOpts, llb.CDIDeviceOptional) + } + opt = append(opt, llb.AddCDIDevice(deviceOpts...)) + } + runDevices, err := dispatchRunDevices(c) + if err != nil { + return err + } + opt = append(opt, runDevices...) + } + shlex := *dopt.shlex shlex.RawQuotes = true shlex.SkipUnsetEnv = true diff --git a/frontend/dockerfile/dockerfile2llb/convert_norundevice.go b/frontend/dockerfile/dockerfile2llb/convert_norundevice.go new file mode 100644 index 000000000000..97a2aeef912a --- /dev/null +++ b/frontend/dockerfile/dockerfile2llb/convert_norundevice.go @@ -0,0 +1,12 @@ +//go:build !dfrundevice + +package dockerfile2llb + +import ( + "github.com/moby/buildkit/client/llb" + "github.com/moby/buildkit/frontend/dockerfile/instructions" +) + +func dispatchRunDevices(_ *instructions.RunCommand) ([]llb.RunOption, error) { + return nil, nil +} diff --git a/frontend/dockerfile/dockerfile2llb/convert_rundevice.go b/frontend/dockerfile/dockerfile2llb/convert_rundevice.go new file mode 100644 index 000000000000..72b44755a420 --- /dev/null +++ b/frontend/dockerfile/dockerfile2llb/convert_rundevice.go @@ -0,0 +1,22 @@ +//go:build dfrundevice + +package dockerfile2llb + +import ( + "github.com/moby/buildkit/client/llb" + "github.com/moby/buildkit/frontend/dockerfile/instructions" +) + +func dispatchRunDevices(c *instructions.RunCommand) ([]llb.RunOption, error) { + var out []llb.RunOption + for _, device := range instructions.GetDevices(c) { + deviceOpts := []llb.CDIDeviceOption{ + llb.CDIDeviceName(device.Name), + } + if !device.Required { + deviceOpts = append(deviceOpts, llb.CDIDeviceOptional) + } + out = append(out, llb.AddCDIDevice(deviceOpts...)) + } + return out, nil +} diff --git a/frontend/dockerfile/dockerfile_rundevice_test.go b/frontend/dockerfile/dockerfile_rundevice_test.go new file mode 100644 index 000000000000..4975fb08fbdc --- /dev/null +++ b/frontend/dockerfile/dockerfile_rundevice_test.go @@ -0,0 +1,79 @@ +//go:build dfrundevice + +package dockerfile + +import ( + "os" + "path/filepath" + "testing" + + "github.com/containerd/continuity/fs/fstest" + "github.com/moby/buildkit/client" + "github.com/moby/buildkit/frontend/dockerui" + "github.com/moby/buildkit/util/testutil/integration" + "github.com/stretchr/testify/require" + "github.com/tonistiigi/fsutil" +) + +func init() { + allTests = append(allTests, integration.TestFuncs( + testDeviceRunEnv, + )...) +} + +func testDeviceRunEnv(t *testing.T, sb integration.Sandbox) { + if sb.Rootless() { + t.SkipNow() + } + + integration.SkipOnPlatform(t, "windows") + f := getFrontend(t, sb) + + require.NoError(t, os.WriteFile(filepath.Join(sb.CDISpecDir(), "vendor1-device.yaml"), []byte(` +cdiVersion: "0.3.0" +kind: "vendor1.com/device" +devices: +- name: foo + containerEdits: + env: + - FOO=injected +`), 0600)) + + dockerfile := []byte(` +FROM busybox AS base +RUN --device=vendor1.com/device=foo,required \ + --device=vendor2.com/device=bar \ + env|sort | tee foo.env +FROM scratch +COPY --from=base /foo.env / +`) + + dir := integration.Tmpdir( + t, + fstest.CreateFile("Dockerfile", dockerfile, 0600), + ) + + c, err := client.New(sb.Context(), sb.Address()) + require.NoError(t, err) + defer c.Close() + + destDir := t.TempDir() + + _, err = f.Solve(sb.Context(), c, client.SolveOpt{ + LocalMounts: map[string]fsutil.FS{ + dockerui.DefaultLocalNameDockerfile: dir, + dockerui.DefaultLocalNameContext: dir, + }, + Exports: []client.ExportEntry{ + { + Type: client.ExporterLocal, + OutputDir: destDir, + }, + }, + }, nil) + require.NoError(t, err) + + dt, err := os.ReadFile(filepath.Join(destDir, "foo.env")) + require.NoError(t, err) + require.Contains(t, string(dt), `FOO=injected`) +} diff --git a/frontend/dockerfile/instructions/commands_rundevice.go b/frontend/dockerfile/instructions/commands_rundevice.go new file mode 100644 index 000000000000..693f28bdc19d --- /dev/null +++ b/frontend/dockerfile/instructions/commands_rundevice.go @@ -0,0 +1,118 @@ +package instructions + +import ( + "strconv" + "strings" + + "github.com/moby/buildkit/util/suggest" + "github.com/pkg/errors" + "github.com/tonistiigi/go-csvvalue" +) + +var devicesKey = "dockerfile/run/devices" + +func init() { + parseRunPreHooks = append(parseRunPreHooks, runDevicePreHook) + parseRunPostHooks = append(parseRunPostHooks, runDevicePostHook) +} + +func runDevicePreHook(cmd *RunCommand, req parseRequest) error { + st := &deviceState{} + st.flag = req.flags.AddStrings("device") + cmd.setExternalValue(devicesKey, st) + return nil +} + +func runDevicePostHook(cmd *RunCommand, req parseRequest) error { + return setDeviceState(cmd) +} + +func setDeviceState(cmd *RunCommand) error { + st := getDeviceState(cmd) + if st == nil { + return errors.Errorf("no device state") + } + devices := make([]*Device, len(st.flag.StringValues)) + for i, str := range st.flag.StringValues { + d, err := ParseDevice(str) + if err != nil { + return err + } + devices[i] = d + } + st.devices = devices + return nil +} + +func getDeviceState(cmd *RunCommand) *deviceState { + v := cmd.getExternalValue(devicesKey) + if v == nil { + return nil + } + return v.(*deviceState) +} + +func GetDevices(cmd *RunCommand) []*Device { + return getDeviceState(cmd).devices +} + +type deviceState struct { + flag *Flag + devices []*Device +} + +type Device struct { + Name string + Required bool +} + +func ParseDevice(val string) (*Device, error) { + fields, err := csvvalue.Fields(val, nil) + if err != nil { + return nil, errors.Wrap(err, "failed to parse csv devices") + } + + d := &Device{} + + for _, field := range fields { + key, value, ok := strings.Cut(field, "=") + key = strings.ToLower(key) + + if !ok { + switch key { + case "required": + d.Required = true + continue + default: + if d.Name == "" { + d.Name = field + continue + } + // any other option requires a value. + return nil, errors.Errorf("invalid field '%s' must be a key=value pair", field) + } + } + + switch key { + case "name": + if d.Name != "" { + return nil, errors.Errorf("device name already set to %s", d.Name) + } + d.Name = value + case "required": + d.Required, err = strconv.ParseBool(value) + if err != nil { + return nil, errors.Errorf("invalid value for %s: %s", key, value) + } + default: + if d.Name == "" { + d.Name = field + continue + } + allKeys := []string{"name", "required"} + return nil, suggest.WrapError(errors.Errorf("unexpected key '%s' in '%s'", key, field), key, allKeys, true) + } + } + + return d, nil +} diff --git a/frontend/dockerfile/instructions/commands_rundevice_test.go b/frontend/dockerfile/instructions/commands_rundevice_test.go new file mode 100644 index 000000000000..79b9be79ff19 --- /dev/null +++ b/frontend/dockerfile/instructions/commands_rundevice_test.go @@ -0,0 +1,69 @@ +package instructions + +import ( + "testing" + + "github.com/pkg/errors" + "github.com/stretchr/testify/require" +) + +func TestParseDevice(t *testing.T) { + cases := []struct { + input string + expected *Device + expectedErr error + }{ + { + input: "vendor1.com/device=foo", + expected: &Device{Name: "vendor1.com/device=foo", Required: false}, + expectedErr: nil, + }, + { + input: "vendor1.com/device", + expected: &Device{Name: "vendor1.com/device", Required: false}, + expectedErr: nil, + }, + { + input: "vendor1.com/device=foo,required", + expected: &Device{Name: "vendor1.com/device=foo", Required: true}, + expectedErr: nil, + }, + { + input: "vendor1.com/device=foo,required=true", + expected: &Device{Name: "vendor1.com/device=foo", Required: true}, + expectedErr: nil, + }, + { + input: "vendor1.com/device=foo,required=false", + expected: &Device{Name: "vendor1.com/device=foo", Required: false}, + expectedErr: nil, + }, + { + input: "name=vendor1.com/device=foo", + expected: &Device{Name: "vendor1.com/device=foo", Required: false}, + expectedErr: nil, + }, + { + input: "name=vendor1.com/device=foo,required", + expected: &Device{Name: "vendor1.com/device=foo", Required: true}, + expectedErr: nil, + }, + { + input: "vendor1.com/device=foo,name=vendor2.com/device=bar", + expected: nil, + expectedErr: errors.New("device name already set to vendor1.com/device=foo"), + }, + } + for _, tt := range cases { + t.Run(tt.input, func(t *testing.T) { + result, err := ParseDevice(tt.input) + if tt.expectedErr != nil { + require.Error(t, err) + require.EqualError(t, err, tt.expectedErr.Error()) + } else { + require.NoError(t, err) + require.Equal(t, tt.expected, result) + } + }) + } +} diff --git a/frontend/dockerfile/release/labs/tags b/frontend/dockerfile/release/labs/tags index 1ebdc80f9956..efaea6dab6da 100644 --- a/frontend/dockerfile/release/labs/tags +++ b/frontend/dockerfile/release/labs/tags @@ -1 +1 @@ -dfrunsecurity dfparents dfexcludepatterns dfcopychmodnonoctal +dfrunsecurity dfparents dfexcludepatterns dfcopychmodnonoctal dfrundevice diff --git a/frontend/dockerui/config.go b/frontend/dockerui/config.go index 368b57080c65..ee8a2667548d 100644 --- a/frontend/dockerui/config.go +++ b/frontend/dockerui/config.go @@ -66,6 +66,7 @@ type Config struct { ShmSize int64 Target string Ulimits []*pb.Ulimit + Devices []*pb.CDIDevice LinterConfig *linter.Config CacheImports []client.CacheOptionsEntry diff --git a/go.mod b/go.mod index fde31734ec8f..2bc7ab934095 100644 --- a/go.mod +++ b/go.mod @@ -107,6 +107,7 @@ require ( google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/protobuf v1.35.2 kernel.org/pub/linux/libs/security/libcap/cap v1.2.73 + tags.cncf.io/container-device-interface v0.8.0 ) require ( @@ -183,7 +184,6 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect kernel.org/pub/linux/libs/security/libcap/psx v1.2.73 // indirect sigs.k8s.io/yaml v1.4.0 // indirect - tags.cncf.io/container-device-interface v0.8.0 // indirect tags.cncf.io/container-device-interface/specs-go v0.8.0 // indirect ) diff --git a/solver/llbsolver/cdidevices/manager.go b/solver/llbsolver/cdidevices/manager.go new file mode 100644 index 000000000000..1996a41c8f7f --- /dev/null +++ b/solver/llbsolver/cdidevices/manager.go @@ -0,0 +1,250 @@ +package cdidevices + +import ( + "context" + "strings" + + "github.com/moby/buildkit/solver/pb" + "github.com/moby/buildkit/util/bklog" + "github.com/moby/locker" + specs "github.com/opencontainers/runtime-spec/specs-go" + "github.com/pkg/errors" + "tags.cncf.io/container-device-interface/pkg/cdi" + "tags.cncf.io/container-device-interface/pkg/parser" +) + +const deviceAnnotationClass = "org.mobyproject.buildkit.device.class" + +var installers = map[string]Setup{} + +type Setup interface { + Validate() error + Run(ctx context.Context) error +} + +// Register registers new setup for a device. +func Register(name string, setup Setup) { + installers[name] = setup +} + +type Device struct { + Name string + AutoAllow bool + OnDemand bool + Annotations map[string]string +} + +type Manager struct { + cache *cdi.Cache + locker *locker.Locker +} + +func NewManager(cache *cdi.Cache) *Manager { + return &Manager{ + cache: cache, + locker: locker.New(), + } +} + +func (m *Manager) ListDevices() []Device { + devs := m.cache.ListDevices() + out := make([]Device, 0, len(devs)) + kinds := make(map[string]struct{}) + for _, dev := range devs { + kind, _, _ := strings.Cut(dev, "=") + dd := m.cache.GetDevice(dev) + out = append(out, Device{ + Name: dev, + AutoAllow: true, // TODO + Annotations: deviceAnnotations(dd), + }) + kinds[kind] = struct{}{} + } + + for k, setup := range installers { + if _, ok := kinds[k]; ok { + continue + } + if err := setup.Validate(); err != nil { + continue + } + out = append(out, Device{ + Name: k, + OnDemand: true, + }) + } + + return out +} + +func (m *Manager) Refresh() error { + return m.cache.Refresh() +} + +func (m *Manager) InjectDevices(spec *specs.Spec, devs ...*pb.CDIDevice) error { + pdevs, err := m.parseDevices(devs...) + if err != nil { + return err + } else if len(pdevs) == 0 { + return nil + } + bklog.G(context.TODO()).Debugf("Injecting devices %v", pdevs) + _, err = m.cache.InjectDevices(spec, pdevs...) + return err +} + +func (m *Manager) parseDevices(devs ...*pb.CDIDevice) ([]string, error) { + var out []string + for _, dev := range devs { + if dev == nil { + continue + } + pdev, err := m.parseDevice(dev) + if err != nil { + return nil, err + } else if len(pdev) == 0 { + continue + } + out = append(out, pdev...) + } + return dedupSlice(out), nil +} + +func (m *Manager) parseDevice(dev *pb.CDIDevice) ([]string, error) { + var out []string + + kind, name, _ := strings.Cut(dev.Name, "=") + + // validate kind + if vendor, class := parser.ParseQualifier(kind); vendor == "" { + return nil, errors.Errorf("invalid device %q", dev.Name) + } else if err := parser.ValidateVendorName(vendor); err != nil { + return nil, errors.Wrapf(err, "invalid device %q", dev.Name) + } else if err := parser.ValidateClassName(class); err != nil { + return nil, errors.Wrapf(err, "invalid device %q", dev.Name) + } + + switch name { + case "": + // first device of kind if no name is specified + for _, d := range m.cache.ListDevices() { + if strings.HasPrefix(d, kind+"=") { + out = append(out, d) + break + } + } + case "*": + // all devices of kind if the name is a wildcard + for _, d := range m.cache.ListDevices() { + if strings.HasPrefix(d, kind+"=") { + out = append(out, d) + } + } + default: + // the specified device + for _, d := range m.cache.ListDevices() { + if d == dev.Name { + out = append(out, d) + break + } + } + if len(out) == 0 { + // check class annotation if name unknown + for _, d := range m.cache.ListDevices() { + if !strings.HasPrefix(d, kind+"=") { + continue + } + if a := deviceAnnotations(m.cache.GetDevice(d)); a != nil { + if class, ok := a[deviceAnnotationClass]; ok && class == name { + out = append(out, d) + } + } + } + } + } + + if len(out) == 0 { + if !dev.Optional { + return nil, errors.Errorf("required device %q is not registered", dev.Name) + } + bklog.G(context.TODO()).Warnf("Optional device %q is not registered", dev.Name) + } + return out, nil +} + +func (m *Manager) hasDevice(name string) bool { + for _, d := range m.cache.ListDevices() { + kind, _, _ := strings.Cut(d, "=") + if kind == name { + return true + } + } + return false +} + +func (m *Manager) OnDemandInstaller(name string) (func(context.Context) error, bool) { + name, _, _ = strings.Cut(name, "=") + + installer, ok := installers[name] + if !ok { + return nil, false + } + + if m.hasDevice(name) { + return nil, false + } + + return func(ctx context.Context) error { + m.locker.Lock(name) + defer m.locker.Unlock(name) + + if m.hasDevice(name) { + return nil + } + + if err := installer.Validate(); err != nil { + return errors.Wrapf(err, "failed to find preconditions for %s device", name) + } + + if err := installer.Run(ctx); err != nil { + return errors.Wrapf(err, "failed to create %s device", name) + } + + if err := m.cache.Refresh(); err != nil { + return errors.Wrapf(err, "failed to refresh CDI cache") + } + + return nil + }, true +} + +func deviceAnnotations(dev *cdi.Device) map[string]string { + if dev == nil { + return nil + } + out := make(map[string]string) + // spec annotations + for k, v := range dev.GetSpec().Annotations { + out[k] = v + } + // device annotations + for k, v := range dev.Device.Annotations { + out[k] = v + } + return out +} + +func dedupSlice(s []string) []string { + if len(s) == 0 { + return s + } + var res []string + seen := make(map[string]struct{}) + for _, val := range s { + if _, ok := seen[val]; !ok { + res = append(res, val) + seen[val] = struct{}{} + } + } + return res +} diff --git a/solver/llbsolver/ops/exec.go b/solver/llbsolver/ops/exec.go index 11184ae74d61..483e76f872b2 100644 --- a/solver/llbsolver/ops/exec.go +++ b/solver/llbsolver/ops/exec.go @@ -199,6 +199,20 @@ func (e *ExecOp) CacheMap(ctx context.Context, g session.Group, index int) (*sol cm.Deps[i].PreprocessFunc = unlazyResultFunc } + for _, d := range e.op.CdiDevices { + setup, ok := e.w.CDIManager().OnDemandInstaller(d.Name) + if ok { + prev := cm.Deps[0].PreprocessFunc + cm.Deps[0].PreprocessFunc = func(ctx context.Context, r solver.Result, g session.Group) error { + if err := prev(ctx, r, g); err != nil { + return err + } + // we could pass glibc/musl type in here based on rootfs to get correct dynamic libs + return setup(ctx) + } + } + } + return cm, true, nil } @@ -432,6 +446,7 @@ func (e *ExecOp) Exec(ctx context.Context, g session.Group, inputs []solver.Resu ReadonlyRootFS: p.ReadonlyRootFS, ExtraHosts: extraHosts, Ulimit: e.op.Meta.Ulimit, + CDIDevices: e.op.CdiDevices, CgroupParent: e.op.Meta.CgroupParent, NetMode: e.op.Network, SecurityMode: e.op.Security, diff --git a/solver/pb/caps.go b/solver/pb/caps.go index b7a802499814..173791e4dd6f 100644 --- a/solver/pb/caps.go +++ b/solver/pb/caps.go @@ -47,6 +47,7 @@ const ( CapExecMetaSecurityDeviceWhitelistV1 apicaps.CapID = "exec.meta.security.devices.v1" CapExecMetaSetsDefaultPath apicaps.CapID = "exec.meta.setsdefaultpath" CapExecMetaUlimit apicaps.CapID = "exec.meta.ulimit" + CapExecMetaCDI apicaps.CapID = "exec.meta.cdi" CapExecMetaRemoveMountStubsRecursive apicaps.CapID = "exec.meta.removemountstubs.recursive" CapExecMountBind apicaps.CapID = "exec.mount.bind" CapExecMountBindReadWriteNoOutput apicaps.CapID = "exec.mount.bind.readwrite-nooutput" @@ -294,6 +295,12 @@ func init() { Status: apicaps.CapStatusExperimental, }) + Caps.Init(apicaps.Cap{ + ID: CapExecMetaCDI, + Enabled: true, + Status: apicaps.CapStatusExperimental, + }) + Caps.Init(apicaps.Cap{ ID: CapExecMountBind, Enabled: true, diff --git a/solver/pb/ops.pb.go b/solver/pb/ops.pb.go index 6975da4cee07..4acac63c24d0 100644 --- a/solver/pb/ops.pb.go +++ b/solver/pb/ops.pb.go @@ -579,11 +579,12 @@ type ExecOp struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Meta *Meta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Mounts []*Mount `protobuf:"bytes,2,rep,name=mounts,proto3" json:"mounts,omitempty"` - Network NetMode `protobuf:"varint,3,opt,name=network,proto3,enum=pb.NetMode" json:"network,omitempty"` - Security SecurityMode `protobuf:"varint,4,opt,name=security,proto3,enum=pb.SecurityMode" json:"security,omitempty"` - Secretenv []*SecretEnv `protobuf:"bytes,5,rep,name=secretenv,proto3" json:"secretenv,omitempty"` + Meta *Meta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Mounts []*Mount `protobuf:"bytes,2,rep,name=mounts,proto3" json:"mounts,omitempty"` + Network NetMode `protobuf:"varint,3,opt,name=network,proto3,enum=pb.NetMode" json:"network,omitempty"` + Security SecurityMode `protobuf:"varint,4,opt,name=security,proto3,enum=pb.SecurityMode" json:"security,omitempty"` + Secretenv []*SecretEnv `protobuf:"bytes,5,rep,name=secretenv,proto3" json:"secretenv,omitempty"` + CdiDevices []*CDIDevice `protobuf:"bytes,6,rep,name=cdiDevices,proto3" json:"cdiDevices,omitempty"` } func (x *ExecOp) Reset() { @@ -651,6 +652,13 @@ func (x *ExecOp) GetSecretenv() []*SecretEnv { return nil } +func (x *ExecOp) GetCdiDevices() []*CDIDevice { + if x != nil { + return x.CdiDevices + } + return nil +} + // Meta is a set of arguments for ExecOp. // Meta is unrelated to LLB metadata. // FIXME: rename (ExecContext? ExecArgs?) @@ -955,6 +963,63 @@ func (x *SecretEnv) GetOptional() bool { return false } +// CDIDevice specifies a CDI device information. +type CDIDevice struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Fully qualified CDI device name (e.g., vendor.com/gpu=gpudevice1) + // https://github.com/cncf-tags/container-device-interface/blob/main/SPEC.md + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Optional defines if CDI device is required. + Optional bool `protobuf:"varint,2,opt,name=optional,proto3" json:"optional,omitempty"` +} + +func (x *CDIDevice) Reset() { + *x = CDIDevice{} + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CDIDevice) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CDIDevice) ProtoMessage() {} + +func (x *CDIDevice) ProtoReflect() protoreflect.Message { + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CDIDevice.ProtoReflect.Descriptor instead. +func (*CDIDevice) Descriptor() ([]byte, []int) { + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{8} +} + +func (x *CDIDevice) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *CDIDevice) GetOptional() bool { + if x != nil { + return x.Optional + } + return false +} + // Mount specifies how to mount an input Op as a filesystem. type Mount struct { state protoimpl.MessageState @@ -977,7 +1042,7 @@ type Mount struct { func (x *Mount) Reset() { *x = Mount{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[8] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -989,7 +1054,7 @@ func (x *Mount) String() string { func (*Mount) ProtoMessage() {} func (x *Mount) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[8] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1002,7 +1067,7 @@ func (x *Mount) ProtoReflect() protoreflect.Message { // Deprecated: Use Mount.ProtoReflect.Descriptor instead. func (*Mount) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{8} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{9} } func (x *Mount) GetInput() int64 { @@ -1101,7 +1166,7 @@ type TmpfsOpt struct { func (x *TmpfsOpt) Reset() { *x = TmpfsOpt{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[9] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1113,7 +1178,7 @@ func (x *TmpfsOpt) String() string { func (*TmpfsOpt) ProtoMessage() {} func (x *TmpfsOpt) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[9] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1126,7 +1191,7 @@ func (x *TmpfsOpt) ProtoReflect() protoreflect.Message { // Deprecated: Use TmpfsOpt.ProtoReflect.Descriptor instead. func (*TmpfsOpt) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{9} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{10} } func (x *TmpfsOpt) GetSize() int64 { @@ -1150,7 +1215,7 @@ type CacheOpt struct { func (x *CacheOpt) Reset() { *x = CacheOpt{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[10] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1162,7 +1227,7 @@ func (x *CacheOpt) String() string { func (*CacheOpt) ProtoMessage() {} func (x *CacheOpt) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[10] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1175,7 +1240,7 @@ func (x *CacheOpt) ProtoReflect() protoreflect.Message { // Deprecated: Use CacheOpt.ProtoReflect.Descriptor instead. func (*CacheOpt) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{10} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{11} } func (x *CacheOpt) GetID() string { @@ -1213,7 +1278,7 @@ type SecretOpt struct { func (x *SecretOpt) Reset() { *x = SecretOpt{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[11] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1225,7 +1290,7 @@ func (x *SecretOpt) String() string { func (*SecretOpt) ProtoMessage() {} func (x *SecretOpt) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[11] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1238,7 +1303,7 @@ func (x *SecretOpt) ProtoReflect() protoreflect.Message { // Deprecated: Use SecretOpt.ProtoReflect.Descriptor instead. func (*SecretOpt) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{11} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{12} } func (x *SecretOpt) GetID() string { @@ -1297,7 +1362,7 @@ type SSHOpt struct { func (x *SSHOpt) Reset() { *x = SSHOpt{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[12] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1309,7 +1374,7 @@ func (x *SSHOpt) String() string { func (*SSHOpt) ProtoMessage() {} func (x *SSHOpt) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[12] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1322,7 +1387,7 @@ func (x *SSHOpt) ProtoReflect() protoreflect.Message { // Deprecated: Use SSHOpt.ProtoReflect.Descriptor instead. func (*SSHOpt) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{12} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{13} } func (x *SSHOpt) GetID() string { @@ -1375,7 +1440,7 @@ type SourceOp struct { func (x *SourceOp) Reset() { *x = SourceOp{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[13] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1387,7 +1452,7 @@ func (x *SourceOp) String() string { func (*SourceOp) ProtoMessage() {} func (x *SourceOp) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[13] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1400,7 +1465,7 @@ func (x *SourceOp) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceOp.ProtoReflect.Descriptor instead. func (*SourceOp) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{13} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{14} } func (x *SourceOp) GetIdentifier() string { @@ -1432,7 +1497,7 @@ type BuildOp struct { func (x *BuildOp) Reset() { *x = BuildOp{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[14] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1444,7 +1509,7 @@ func (x *BuildOp) String() string { func (*BuildOp) ProtoMessage() {} func (x *BuildOp) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[14] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1457,7 +1522,7 @@ func (x *BuildOp) ProtoReflect() protoreflect.Message { // Deprecated: Use BuildOp.ProtoReflect.Descriptor instead. func (*BuildOp) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{14} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{15} } func (x *BuildOp) GetBuilder() int64 { @@ -1499,7 +1564,7 @@ type BuildInput struct { func (x *BuildInput) Reset() { *x = BuildInput{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[15] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1511,7 +1576,7 @@ func (x *BuildInput) String() string { func (*BuildInput) ProtoMessage() {} func (x *BuildInput) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[15] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1524,7 +1589,7 @@ func (x *BuildInput) ProtoReflect() protoreflect.Message { // Deprecated: Use BuildInput.ProtoReflect.Descriptor instead. func (*BuildInput) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{15} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{16} } func (x *BuildInput) GetInput() int64 { @@ -1553,7 +1618,7 @@ type OpMetadata struct { func (x *OpMetadata) Reset() { *x = OpMetadata{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[16] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1565,7 +1630,7 @@ func (x *OpMetadata) String() string { func (*OpMetadata) ProtoMessage() {} func (x *OpMetadata) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[16] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1578,7 +1643,7 @@ func (x *OpMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use OpMetadata.ProtoReflect.Descriptor instead. func (*OpMetadata) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{16} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{17} } func (x *OpMetadata) GetIgnoreCache() bool { @@ -1628,7 +1693,7 @@ type Source struct { func (x *Source) Reset() { *x = Source{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[17] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1640,7 +1705,7 @@ func (x *Source) String() string { func (*Source) ProtoMessage() {} func (x *Source) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[17] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1653,7 +1718,7 @@ func (x *Source) ProtoReflect() protoreflect.Message { // Deprecated: Use Source.ProtoReflect.Descriptor instead. func (*Source) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{17} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{18} } func (x *Source) GetLocations() map[string]*Locations { @@ -1681,7 +1746,7 @@ type Locations struct { func (x *Locations) Reset() { *x = Locations{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[18] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1693,7 +1758,7 @@ func (x *Locations) String() string { func (*Locations) ProtoMessage() {} func (x *Locations) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[18] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1706,7 +1771,7 @@ func (x *Locations) ProtoReflect() protoreflect.Message { // Deprecated: Use Locations.ProtoReflect.Descriptor instead. func (*Locations) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{18} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{19} } func (x *Locations) GetLocations() []*Location { @@ -1730,7 +1795,7 @@ type SourceInfo struct { func (x *SourceInfo) Reset() { *x = SourceInfo{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[19] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1742,7 +1807,7 @@ func (x *SourceInfo) String() string { func (*SourceInfo) ProtoMessage() {} func (x *SourceInfo) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[19] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1755,7 +1820,7 @@ func (x *SourceInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceInfo.ProtoReflect.Descriptor instead. func (*SourceInfo) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{19} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{20} } func (x *SourceInfo) GetFilename() string { @@ -1798,7 +1863,7 @@ type Location struct { func (x *Location) Reset() { *x = Location{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[20] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1810,7 +1875,7 @@ func (x *Location) String() string { func (*Location) ProtoMessage() {} func (x *Location) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[20] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1823,7 +1888,7 @@ func (x *Location) ProtoReflect() protoreflect.Message { // Deprecated: Use Location.ProtoReflect.Descriptor instead. func (*Location) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{20} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{21} } func (x *Location) GetSourceIndex() int32 { @@ -1852,7 +1917,7 @@ type Range struct { func (x *Range) Reset() { *x = Range{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[21] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1864,7 +1929,7 @@ func (x *Range) String() string { func (*Range) ProtoMessage() {} func (x *Range) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[21] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1877,7 +1942,7 @@ func (x *Range) ProtoReflect() protoreflect.Message { // Deprecated: Use Range.ProtoReflect.Descriptor instead. func (*Range) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{21} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{22} } func (x *Range) GetStart() *Position { @@ -1906,7 +1971,7 @@ type Position struct { func (x *Position) Reset() { *x = Position{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[22] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1918,7 +1983,7 @@ func (x *Position) String() string { func (*Position) ProtoMessage() {} func (x *Position) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[22] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1931,7 +1996,7 @@ func (x *Position) ProtoReflect() protoreflect.Message { // Deprecated: Use Position.ProtoReflect.Descriptor instead. func (*Position) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{22} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{23} } func (x *Position) GetLine() int32 { @@ -1958,7 +2023,7 @@ type ExportCache struct { func (x *ExportCache) Reset() { *x = ExportCache{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[23] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1970,7 +2035,7 @@ func (x *ExportCache) String() string { func (*ExportCache) ProtoMessage() {} func (x *ExportCache) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[23] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1983,7 +2048,7 @@ func (x *ExportCache) ProtoReflect() protoreflect.Message { // Deprecated: Use ExportCache.ProtoReflect.Descriptor instead. func (*ExportCache) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{23} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{24} } func (x *ExportCache) GetValue() bool { @@ -2005,7 +2070,7 @@ type ProgressGroup struct { func (x *ProgressGroup) Reset() { *x = ProgressGroup{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[24] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2017,7 +2082,7 @@ func (x *ProgressGroup) String() string { func (*ProgressGroup) ProtoMessage() {} func (x *ProgressGroup) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[24] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2030,7 +2095,7 @@ func (x *ProgressGroup) ProtoReflect() protoreflect.Message { // Deprecated: Use ProgressGroup.ProtoReflect.Descriptor instead. func (*ProgressGroup) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{24} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{25} } func (x *ProgressGroup) GetId() string { @@ -2068,7 +2133,7 @@ type ProxyEnv struct { func (x *ProxyEnv) Reset() { *x = ProxyEnv{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[25] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2080,7 +2145,7 @@ func (x *ProxyEnv) String() string { func (*ProxyEnv) ProtoMessage() {} func (x *ProxyEnv) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[25] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2093,7 +2158,7 @@ func (x *ProxyEnv) ProtoReflect() protoreflect.Message { // Deprecated: Use ProxyEnv.ProtoReflect.Descriptor instead. func (*ProxyEnv) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{25} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{26} } func (x *ProxyEnv) GetHttpProxy() string { @@ -2142,7 +2207,7 @@ type WorkerConstraints struct { func (x *WorkerConstraints) Reset() { *x = WorkerConstraints{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[26] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2154,7 +2219,7 @@ func (x *WorkerConstraints) String() string { func (*WorkerConstraints) ProtoMessage() {} func (x *WorkerConstraints) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[26] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2167,7 +2232,7 @@ func (x *WorkerConstraints) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkerConstraints.ProtoReflect.Descriptor instead. func (*WorkerConstraints) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{26} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{27} } func (x *WorkerConstraints) GetFilter() []string { @@ -2194,7 +2259,7 @@ type Definition struct { func (x *Definition) Reset() { *x = Definition{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[27] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2206,7 +2271,7 @@ func (x *Definition) String() string { func (*Definition) ProtoMessage() {} func (x *Definition) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[27] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2219,7 +2284,7 @@ func (x *Definition) ProtoReflect() protoreflect.Message { // Deprecated: Use Definition.ProtoReflect.Descriptor instead. func (*Definition) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{27} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{28} } func (x *Definition) GetDef() [][]byte { @@ -2253,7 +2318,7 @@ type FileOp struct { func (x *FileOp) Reset() { *x = FileOp{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[28] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2265,7 +2330,7 @@ func (x *FileOp) String() string { func (*FileOp) ProtoMessage() {} func (x *FileOp) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[28] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2278,7 +2343,7 @@ func (x *FileOp) ProtoReflect() protoreflect.Message { // Deprecated: Use FileOp.ProtoReflect.Descriptor instead. func (*FileOp) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{28} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{29} } func (x *FileOp) GetActions() []*FileAction { @@ -2309,7 +2374,7 @@ type FileAction struct { func (x *FileAction) Reset() { *x = FileAction{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[29] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2321,7 +2386,7 @@ func (x *FileAction) String() string { func (*FileAction) ProtoMessage() {} func (x *FileAction) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[29] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2334,7 +2399,7 @@ func (x *FileAction) ProtoReflect() protoreflect.Message { // Deprecated: Use FileAction.ProtoReflect.Descriptor instead. func (*FileAction) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{29} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{30} } func (x *FileAction) GetInput() int64 { @@ -2478,7 +2543,7 @@ type FileActionCopy struct { func (x *FileActionCopy) Reset() { *x = FileActionCopy{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[30] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2490,7 +2555,7 @@ func (x *FileActionCopy) String() string { func (*FileActionCopy) ProtoMessage() {} func (x *FileActionCopy) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[30] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2503,7 +2568,7 @@ func (x *FileActionCopy) ProtoReflect() protoreflect.Message { // Deprecated: Use FileActionCopy.ProtoReflect.Descriptor instead. func (*FileActionCopy) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{30} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{31} } func (x *FileActionCopy) GetSrc() string { @@ -2630,7 +2695,7 @@ type FileActionMkFile struct { func (x *FileActionMkFile) Reset() { *x = FileActionMkFile{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[31] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2642,7 +2707,7 @@ func (x *FileActionMkFile) String() string { func (*FileActionMkFile) ProtoMessage() {} func (x *FileActionMkFile) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[31] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2655,7 +2720,7 @@ func (x *FileActionMkFile) ProtoReflect() protoreflect.Message { // Deprecated: Use FileActionMkFile.ProtoReflect.Descriptor instead. func (*FileActionMkFile) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{31} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{32} } func (x *FileActionMkFile) GetPath() string { @@ -2710,7 +2775,7 @@ type FileActionSymlink struct { func (x *FileActionSymlink) Reset() { *x = FileActionSymlink{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[32] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2722,7 +2787,7 @@ func (x *FileActionSymlink) String() string { func (*FileActionSymlink) ProtoMessage() {} func (x *FileActionSymlink) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[32] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2735,7 +2800,7 @@ func (x *FileActionSymlink) ProtoReflect() protoreflect.Message { // Deprecated: Use FileActionSymlink.ProtoReflect.Descriptor instead. func (*FileActionSymlink) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{32} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{33} } func (x *FileActionSymlink) GetOldpath() string { @@ -2785,7 +2850,7 @@ type FileActionMkDir struct { func (x *FileActionMkDir) Reset() { *x = FileActionMkDir{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[33] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2797,7 +2862,7 @@ func (x *FileActionMkDir) String() string { func (*FileActionMkDir) ProtoMessage() {} func (x *FileActionMkDir) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[33] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2810,7 +2875,7 @@ func (x *FileActionMkDir) ProtoReflect() protoreflect.Message { // Deprecated: Use FileActionMkDir.ProtoReflect.Descriptor instead. func (*FileActionMkDir) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{33} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{34} } func (x *FileActionMkDir) GetPath() string { @@ -2863,7 +2928,7 @@ type FileActionRm struct { func (x *FileActionRm) Reset() { *x = FileActionRm{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[34] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2875,7 +2940,7 @@ func (x *FileActionRm) String() string { func (*FileActionRm) ProtoMessage() {} func (x *FileActionRm) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[34] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2888,7 +2953,7 @@ func (x *FileActionRm) ProtoReflect() protoreflect.Message { // Deprecated: Use FileActionRm.ProtoReflect.Descriptor instead. func (*FileActionRm) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{34} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{35} } func (x *FileActionRm) GetPath() string { @@ -2923,7 +2988,7 @@ type ChownOpt struct { func (x *ChownOpt) Reset() { *x = ChownOpt{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[35] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2935,7 +3000,7 @@ func (x *ChownOpt) String() string { func (*ChownOpt) ProtoMessage() {} func (x *ChownOpt) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[35] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2948,7 +3013,7 @@ func (x *ChownOpt) ProtoReflect() protoreflect.Message { // Deprecated: Use ChownOpt.ProtoReflect.Descriptor instead. func (*ChownOpt) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{35} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{36} } func (x *ChownOpt) GetUser() *UserOpt { @@ -2981,7 +3046,7 @@ type UserOpt struct { func (x *UserOpt) Reset() { *x = UserOpt{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[36] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2993,7 +3058,7 @@ func (x *UserOpt) String() string { func (*UserOpt) ProtoMessage() {} func (x *UserOpt) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[36] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3006,7 +3071,7 @@ func (x *UserOpt) ProtoReflect() protoreflect.Message { // Deprecated: Use UserOpt.ProtoReflect.Descriptor instead. func (*UserOpt) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{36} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{37} } func (m *UserOpt) GetUser() isUserOpt_User { @@ -3057,7 +3122,7 @@ type NamedUserOpt struct { func (x *NamedUserOpt) Reset() { *x = NamedUserOpt{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[37] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3069,7 +3134,7 @@ func (x *NamedUserOpt) String() string { func (*NamedUserOpt) ProtoMessage() {} func (x *NamedUserOpt) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[37] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3082,7 +3147,7 @@ func (x *NamedUserOpt) ProtoReflect() protoreflect.Message { // Deprecated: Use NamedUserOpt.ProtoReflect.Descriptor instead. func (*NamedUserOpt) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{37} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{38} } func (x *NamedUserOpt) GetName() string { @@ -3109,7 +3174,7 @@ type MergeInput struct { func (x *MergeInput) Reset() { *x = MergeInput{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[38] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3121,7 +3186,7 @@ func (x *MergeInput) String() string { func (*MergeInput) ProtoMessage() {} func (x *MergeInput) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[38] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3134,7 +3199,7 @@ func (x *MergeInput) ProtoReflect() protoreflect.Message { // Deprecated: Use MergeInput.ProtoReflect.Descriptor instead. func (*MergeInput) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{38} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{39} } func (x *MergeInput) GetInput() int64 { @@ -3154,7 +3219,7 @@ type MergeOp struct { func (x *MergeOp) Reset() { *x = MergeOp{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[39] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3166,7 +3231,7 @@ func (x *MergeOp) String() string { func (*MergeOp) ProtoMessage() {} func (x *MergeOp) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[39] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3179,7 +3244,7 @@ func (x *MergeOp) ProtoReflect() protoreflect.Message { // Deprecated: Use MergeOp.ProtoReflect.Descriptor instead. func (*MergeOp) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{39} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{40} } func (x *MergeOp) GetInputs() []*MergeInput { @@ -3199,7 +3264,7 @@ type LowerDiffInput struct { func (x *LowerDiffInput) Reset() { *x = LowerDiffInput{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[40] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3211,7 +3276,7 @@ func (x *LowerDiffInput) String() string { func (*LowerDiffInput) ProtoMessage() {} func (x *LowerDiffInput) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[40] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3224,7 +3289,7 @@ func (x *LowerDiffInput) ProtoReflect() protoreflect.Message { // Deprecated: Use LowerDiffInput.ProtoReflect.Descriptor instead. func (*LowerDiffInput) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{40} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{41} } func (x *LowerDiffInput) GetInput() int64 { @@ -3244,7 +3309,7 @@ type UpperDiffInput struct { func (x *UpperDiffInput) Reset() { *x = UpperDiffInput{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[41] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3256,7 +3321,7 @@ func (x *UpperDiffInput) String() string { func (*UpperDiffInput) ProtoMessage() {} func (x *UpperDiffInput) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[41] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3269,7 +3334,7 @@ func (x *UpperDiffInput) ProtoReflect() protoreflect.Message { // Deprecated: Use UpperDiffInput.ProtoReflect.Descriptor instead. func (*UpperDiffInput) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{41} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{42} } func (x *UpperDiffInput) GetInput() int64 { @@ -3290,7 +3355,7 @@ type DiffOp struct { func (x *DiffOp) Reset() { *x = DiffOp{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[42] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3302,7 +3367,7 @@ func (x *DiffOp) String() string { func (*DiffOp) ProtoMessage() {} func (x *DiffOp) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[42] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3315,7 +3380,7 @@ func (x *DiffOp) ProtoReflect() protoreflect.Message { // Deprecated: Use DiffOp.ProtoReflect.Descriptor instead. func (*DiffOp) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{42} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{43} } func (x *DiffOp) GetLower() *LowerDiffInput { @@ -3373,7 +3438,7 @@ var file_github_com_moby_buildkit_solver_pb_ops_proto_rawDesc = []byte{ 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x35, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0xcb, 0x01, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0xfa, 0x01, 0x0a, 0x06, 0x45, 0x78, 0x65, 0x63, 0x4f, 0x70, 0x12, 0x1c, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x70, 0x62, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x06, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, @@ -3386,361 +3451,368 @@ var file_github_com_moby_buildkit_solver_pb_ops_proto_rawDesc = []byte{ 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x08, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2b, 0x0a, 0x09, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x76, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x45, 0x6e, 0x76, - 0x52, 0x09, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x76, 0x22, 0xf3, 0x02, 0x0a, 0x04, - 0x4d, 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x77, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x77, 0x64, 0x12, 0x12, 0x0a, 0x04, - 0x75, 0x73, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, - 0x12, 0x29, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x65, 0x6e, 0x76, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x45, 0x6e, - 0x76, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x45, 0x6e, 0x76, 0x12, 0x2a, 0x0a, 0x0a, 0x65, - 0x78, 0x74, 0x72, 0x61, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x0a, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x49, 0x50, 0x52, 0x0a, 0x65, 0x78, 0x74, - 0x72, 0x61, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x06, 0x75, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x09, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x52, - 0x06, 0x75, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, - 0x67, 0x72, 0x6f, 0x75, 0x70, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x3c, 0x0a, 0x19, 0x72, + 0x52, 0x09, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x76, 0x12, 0x2d, 0x0a, 0x0a, 0x63, + 0x64, 0x69, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x44, 0x49, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x0a, + 0x63, 0x64, 0x69, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0xf3, 0x02, 0x0a, 0x04, 0x4d, + 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x77, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x77, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x75, + 0x73, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, + 0x29, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x65, 0x6e, 0x76, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x45, 0x6e, 0x76, + 0x52, 0x08, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x45, 0x6e, 0x76, 0x12, 0x2a, 0x0a, 0x0a, 0x65, 0x78, + 0x74, 0x72, 0x61, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, + 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x49, 0x50, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x72, + 0x61, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x06, 0x75, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x09, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x06, + 0x75, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x3c, 0x0a, 0x19, 0x72, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x74, 0x75, 0x62, 0x73, 0x52, 0x65, + 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x74, 0x75, 0x62, 0x73, 0x52, - 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, - 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x74, 0x75, 0x62, 0x73, - 0x52, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x45, 0x78, 0x69, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, - 0x05, 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x45, 0x78, 0x69, 0x74, 0x43, 0x6f, 0x64, 0x65, - 0x73, 0x22, 0x2c, 0x0a, 0x06, 0x48, 0x6f, 0x73, 0x74, 0x49, 0x50, 0x12, 0x12, 0x0a, 0x04, 0x48, - 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x48, 0x6f, 0x73, 0x74, 0x12, - 0x0e, 0x0a, 0x02, 0x49, 0x50, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x50, 0x22, - 0x44, 0x0a, 0x06, 0x55, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x53, 0x6f, 0x66, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x53, 0x6f, 0x66, - 0x74, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x04, 0x48, 0x61, 0x72, 0x64, 0x22, 0x4b, 0x0a, 0x09, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x45, - 0x6e, 0x76, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x61, 0x6c, 0x22, 0xaa, 0x03, 0x0a, 0x05, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, - 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, - 0x75, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x12, - 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, - 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, - 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, - 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x12, 0x2b, 0x0a, 0x09, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x54, - 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x4d, - 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x08, 0x54, 0x6d, 0x70, 0x66, 0x73, 0x4f, 0x70, 0x74, 0x18, - 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x6d, 0x70, 0x66, 0x73, - 0x4f, 0x70, 0x74, 0x52, 0x08, 0x54, 0x6d, 0x70, 0x66, 0x73, 0x4f, 0x70, 0x74, 0x12, 0x28, 0x0a, - 0x08, 0x63, 0x61, 0x63, 0x68, 0x65, 0x4f, 0x70, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x4f, 0x70, 0x74, 0x52, 0x08, 0x63, - 0x61, 0x63, 0x68, 0x65, 0x4f, 0x70, 0x74, 0x12, 0x2b, 0x0a, 0x09, 0x73, 0x65, 0x63, 0x72, 0x65, - 0x74, 0x4f, 0x70, 0x74, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, - 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x52, 0x09, 0x73, 0x65, 0x63, 0x72, 0x65, - 0x74, 0x4f, 0x70, 0x74, 0x12, 0x22, 0x0a, 0x06, 0x53, 0x53, 0x48, 0x4f, 0x70, 0x74, 0x18, 0x16, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x53, 0x48, 0x4f, 0x70, 0x74, - 0x52, 0x06, 0x53, 0x53, 0x48, 0x4f, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x49, 0x44, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x49, 0x44, 0x12, 0x39, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x43, - 0x61, 0x63, 0x68, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x62, 0x2e, - 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x22, - 0x1e, 0x0a, 0x08, 0x54, 0x6d, 0x70, 0x66, 0x73, 0x4f, 0x70, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, - 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, - 0x49, 0x0a, 0x08, 0x43, 0x61, 0x63, 0x68, 0x65, 0x4f, 0x70, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, - 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x2d, 0x0a, 0x07, 0x73, - 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x70, - 0x62, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4f, 0x70, - 0x74, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x6f, 0x0a, 0x09, 0x53, 0x65, - 0x63, 0x72, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x69, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x67, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6d, - 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, - 0x1a, 0x0a, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0x6c, 0x0a, 0x06, 0x53, - 0x53, 0x48, 0x4f, 0x70, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x67, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, - 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0x93, 0x01, 0x0a, 0x08, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x4f, 0x70, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x2d, 0x0a, 0x05, 0x61, 0x74, 0x74, 0x72, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x4f, 0x70, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, - 0x61, 0x74, 0x74, 0x72, 0x73, 0x1a, 0x38, 0x0a, 0x0a, 0x41, 0x74, 0x74, 0x72, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, - 0xa9, 0x02, 0x0a, 0x07, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4f, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x62, - 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x62, 0x75, - 0x69, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, - 0x4f, 0x70, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, - 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x20, 0x0a, 0x03, 0x64, 0x65, 0x66, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x64, 0x65, 0x66, 0x12, 0x2c, 0x0a, 0x05, 0x61, 0x74, 0x74, 0x72, - 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x62, 0x2e, 0x42, 0x75, 0x69, - 0x6c, 0x64, 0x4f, 0x70, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x05, 0x61, 0x74, 0x74, 0x72, 0x73, 0x1a, 0x49, 0x0a, 0x0b, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x24, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x42, 0x75, 0x69, 0x6c, - 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x1a, 0x38, 0x0a, 0x0a, 0x41, 0x74, 0x74, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x45, 0x78, 0x69, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x05, + 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x45, 0x78, 0x69, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x73, + 0x22, 0x2c, 0x0a, 0x06, 0x48, 0x6f, 0x73, 0x74, 0x49, 0x50, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x6f, + 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x0e, + 0x0a, 0x02, 0x49, 0x50, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x50, 0x22, 0x44, + 0x0a, 0x06, 0x55, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x53, 0x6f, 0x66, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x53, 0x6f, 0x66, 0x74, + 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, + 0x48, 0x61, 0x72, 0x64, 0x22, 0x4b, 0x0a, 0x09, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x45, 0x6e, + 0x76, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, + 0x44, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x22, 0x3b, 0x0a, 0x09, 0x43, 0x44, 0x49, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0xaa, + 0x03, 0x0a, 0x05, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x1a, + 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, + 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, + 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, + 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, + 0x6c, 0x79, 0x12, 0x2b, 0x0a, 0x09, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x28, 0x0a, 0x08, 0x54, 0x6d, 0x70, 0x66, 0x73, 0x4f, 0x70, 0x74, 0x18, 0x13, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x6d, 0x70, 0x66, 0x73, 0x4f, 0x70, 0x74, 0x52, + 0x08, 0x54, 0x6d, 0x70, 0x66, 0x73, 0x4f, 0x70, 0x74, 0x12, 0x28, 0x0a, 0x08, 0x63, 0x61, 0x63, + 0x68, 0x65, 0x4f, 0x70, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, + 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x4f, 0x70, 0x74, 0x52, 0x08, 0x63, 0x61, 0x63, 0x68, 0x65, + 0x4f, 0x70, 0x74, 0x12, 0x2b, 0x0a, 0x09, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4f, 0x70, 0x74, + 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x63, 0x72, + 0x65, 0x74, 0x4f, 0x70, 0x74, 0x52, 0x09, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4f, 0x70, 0x74, + 0x12, 0x22, 0x0a, 0x06, 0x53, 0x53, 0x48, 0x4f, 0x70, 0x74, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x53, 0x48, 0x4f, 0x70, 0x74, 0x52, 0x06, 0x53, 0x53, + 0x48, 0x4f, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x49, 0x44, + 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x49, 0x44, + 0x12, 0x39, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, + 0x18, 0x18, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, + 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x0c, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x22, 0x1e, 0x0a, 0x08, 0x54, + 0x6d, 0x70, 0x66, 0x73, 0x4f, 0x70, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x49, 0x0a, 0x08, 0x43, + 0x61, 0x63, 0x68, 0x65, 0x4f, 0x70, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x2d, 0x0a, 0x07, 0x73, 0x68, 0x61, 0x72, 0x69, + 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x61, + 0x63, 0x68, 0x65, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4f, 0x70, 0x74, 0x52, 0x07, 0x73, + 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x6f, 0x0a, 0x09, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, + 0x4f, 0x70, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x49, 0x44, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x03, 0x67, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0x6c, 0x0a, 0x06, 0x53, 0x53, 0x48, 0x4f, 0x70, + 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, + 0x44, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, + 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x03, 0x67, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0x93, 0x01, 0x0a, 0x08, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x4f, 0x70, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x12, 0x2d, 0x0a, 0x05, 0x61, 0x74, 0x74, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4f, 0x70, 0x2e, + 0x41, 0x74, 0x74, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x61, 0x74, 0x74, 0x72, + 0x73, 0x1a, 0x38, 0x0a, 0x0a, 0x41, 0x74, 0x74, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x22, 0x0a, 0x0a, 0x42, - 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, - 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, - 0x87, 0x03, 0x0a, 0x0a, 0x4f, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, - 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x12, 0x41, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x62, 0x2e, 0x4f, 0x70, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x0c, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, - 0x61, 0x63, 0x68, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62, 0x2e, - 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x0b, 0x65, 0x78, 0x70, - 0x6f, 0x72, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x63, 0x61, 0x70, 0x73, - 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x62, 0x2e, 0x4f, 0x70, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x61, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x04, 0x63, 0x61, 0x70, 0x73, 0x12, 0x38, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, - 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, - 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x1a, 0x3e, 0x0a, 0x10, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x1a, 0x37, 0x0a, 0x09, 0x43, 0x61, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb4, 0x01, 0x0a, 0x06, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x24, 0x0a, - 0x05, 0x69, 0x6e, 0x66, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, - 0x62, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x69, 0x6e, - 0x66, 0x6f, 0x73, 0x1a, 0x4b, 0x0a, 0x0e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x6f, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0x37, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2a, 0x0a, - 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, - 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x88, 0x01, 0x0a, 0x0a, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x0a, 0x64, 0x65, 0x66, 0x69, - 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, - 0x62, 0x2e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x64, 0x65, - 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, - 0x75, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, - 0x75, 0x61, 0x67, 0x65, 0x22, 0x4f, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x12, 0x21, 0x0a, 0x06, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x72, - 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x05, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x22, - 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, - 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x65, - 0x6e, 0x64, 0x22, 0x3c, 0x0a, 0x08, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, - 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x6c, 0x69, - 0x6e, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, - 0x22, 0x23, 0x0a, 0x0b, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x47, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, - 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x77, 0x65, - 0x61, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x22, 0x9f, - 0x01, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x45, 0x6e, 0x76, 0x12, 0x1d, 0x0a, 0x0a, 0x68, - 0x74, 0x74, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x68, 0x74, 0x74, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x74, - 0x74, 0x70, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x68, 0x74, 0x74, 0x70, 0x73, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x66, - 0x74, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x66, 0x74, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x5f, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x6f, 0x50, 0x72, - 0x6f, 0x78, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x6c, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x6c, 0x6c, 0x50, 0x72, 0x6f, 0x78, 0x79, - 0x22, 0x2b, 0x0a, 0x11, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, - 0x61, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0xc9, 0x01, - 0x0a, 0x0a, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, - 0x64, 0x65, 0x66, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x03, 0x64, 0x65, 0x66, 0x12, 0x38, - 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x1a, 0x4b, 0x0a, 0x0d, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x24, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, - 0x2e, 0x70, 0x62, 0x2e, 0x4f, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x32, 0x0a, 0x06, 0x46, 0x69, 0x6c, - 0x65, 0x4f, 0x70, 0x12, 0x28, 0x0a, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xca, 0x02, - 0x0a, 0x0a, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, - 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, - 0x75, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x49, - 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x12, 0x28, 0x0a, 0x04, 0x63, 0x6f, 0x70, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6f, 0x70, 0x79, 0x48, 0x00, 0x52, 0x04, 0x63, 0x6f, 0x70, 0x79, 0x12, 0x2e, 0x0a, 0x06, - 0x6d, 0x6b, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, - 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x46, 0x69, - 0x6c, 0x65, 0x48, 0x00, 0x52, 0x06, 0x6d, 0x6b, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x2b, 0x0a, 0x05, - 0x6d, 0x6b, 0x64, 0x69, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x62, - 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x44, 0x69, 0x72, - 0x48, 0x00, 0x52, 0x05, 0x6d, 0x6b, 0x64, 0x69, 0x72, 0x12, 0x22, 0x0a, 0x02, 0x72, 0x6d, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6d, 0x48, 0x00, 0x52, 0x02, 0x72, 0x6d, 0x12, 0x31, 0x0a, - 0x07, 0x73, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, - 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x79, - 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x48, 0x00, 0x52, 0x07, 0x73, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, - 0x42, 0x08, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xde, 0x04, 0x0a, 0x0e, 0x46, - 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x70, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x73, 0x72, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x72, 0x63, 0x12, - 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, - 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x6f, 0x77, 0x6e, 0x4f, 0x70, 0x74, - 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x66, - 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0d, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, - 0x6b, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x72, 0x43, 0x6f, 0x70, 0x79, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, 0x72, 0x43, - 0x6f, 0x70, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x20, 0x61, - 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x44, 0x6f, 0x63, 0x6b, - 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x20, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x55, 0x6e, - 0x70, 0x61, 0x63, 0x6b, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, - 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, - 0x24, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x6c, - 0x64, 0x63, 0x61, 0x72, 0x64, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x57, 0x69, 0x6c, - 0x64, 0x63, 0x61, 0x72, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70, - 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x12, 0x29, - 0x0a, 0x10, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, - 0x6e, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, - 0x65, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x12, 0x46, 0x0a, 0x1e, 0x61, 0x6c, 0x77, - 0x61, 0x79, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, 0x69, - 0x6e, 0x67, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x1e, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, - 0x45, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, - 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x18, 0x0f, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x22, 0x90, 0x01, 0x0a, 0x10, - 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x46, 0x69, 0x6c, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x05, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, - 0x2e, 0x43, 0x68, 0x6f, 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x89, - 0x01, 0x0a, 0x11, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x79, 0x6d, - 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x6c, 0x64, 0x70, 0x61, 0x74, 0x68, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x6c, 0x64, 0x70, 0x61, 0x74, 0x68, 0x12, 0x18, - 0x0a, 0x07, 0x6e, 0x65, 0x77, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x6e, 0x65, 0x77, 0x70, 0x61, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, - 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x6f, - 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x9d, 0x01, 0x0a, 0x0f, 0x46, - 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x44, 0x69, 0x72, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x61, 0x6b, 0x65, 0x50, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6d, 0x61, 0x6b, - 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa9, 0x02, 0x0a, 0x07, + 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4f, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, + 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4f, 0x70, 0x2e, 0x49, + 0x6e, 0x70, 0x75, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, + 0x74, 0x73, 0x12, 0x20, 0x0a, 0x03, 0x64, 0x65, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x03, 0x64, 0x65, 0x66, 0x12, 0x2c, 0x0a, 0x05, 0x61, 0x74, 0x74, 0x72, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x62, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4f, 0x70, + 0x2e, 0x41, 0x74, 0x74, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x61, 0x74, 0x74, + 0x72, 0x73, 0x1a, 0x49, 0x0a, 0x0b, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x24, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x70, + 0x75, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x38, 0x0a, + 0x0a, 0x41, 0x74, 0x74, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x22, 0x0a, 0x0a, 0x42, 0x75, 0x69, 0x6c, 0x64, + 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x87, 0x03, 0x0a, 0x0a, + 0x4f, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, + 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x41, 0x0a, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x62, 0x2e, 0x4f, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x32, 0x0a, 0x0c, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x78, 0x70, 0x6f, + 0x72, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x0b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, + 0x61, 0x63, 0x68, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x63, 0x61, 0x70, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x62, 0x2e, 0x4f, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x43, 0x61, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x63, 0x61, + 0x70, 0x73, 0x12, 0x38, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x62, 0x2e, + 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x0d, 0x70, + 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x1a, 0x3e, 0x0a, 0x10, + 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x37, 0x0a, 0x09, + 0x43, 0x61, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb4, 0x01, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x12, 0x37, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, + 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, + 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x24, 0x0a, 0x05, 0x69, 0x6e, 0x66, + 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x69, 0x6e, 0x66, 0x6f, 0x73, 0x1a, + 0x4b, 0x0a, 0x0e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x37, 0x0a, 0x09, + 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2a, 0x0a, 0x09, 0x6c, 0x6f, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, + 0x62, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x88, 0x01, 0x0a, 0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, + 0x64, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, + 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, + 0x22, 0x4f, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x21, + 0x0a, 0x06, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, + 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x72, 0x61, 0x6e, 0x67, 0x65, + 0x73, 0x22, 0x4b, 0x0a, 0x05, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x05, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x50, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x1e, + 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, + 0x2e, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x3c, + 0x0a, 0x08, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, + 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x09, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x22, 0x23, 0x0a, 0x0b, + 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x22, 0x47, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x22, 0x9f, 0x01, 0x0a, 0x08, 0x50, + 0x72, 0x6f, 0x78, 0x79, 0x45, 0x6e, 0x76, 0x12, 0x1d, 0x0a, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x5f, + 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x68, 0x74, 0x74, + 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x74, 0x74, 0x70, 0x73, 0x5f, + 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x74, 0x74, + 0x70, 0x73, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x74, 0x70, 0x5f, 0x70, + 0x72, 0x6f, 0x78, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x74, 0x70, 0x50, + 0x72, 0x6f, 0x78, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x6f, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, + 0x1b, 0x0a, 0x09, 0x61, 0x6c, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x61, 0x6c, 0x6c, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x22, 0x2b, 0x0a, 0x11, + 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, + 0x73, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0xc9, 0x01, 0x0a, 0x0a, 0x44, 0x65, + 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x65, 0x66, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x03, 0x64, 0x65, 0x66, 0x12, 0x38, 0x0a, 0x08, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, + 0x62, 0x2e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x52, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x1a, 0x4b, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x24, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, + 0x4f, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x32, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x12, + 0x28, 0x0a, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xca, 0x02, 0x0a, 0x0a, 0x46, 0x69, + 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x26, + 0x0a, 0x0e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x70, 0x75, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, + 0x79, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x28, + 0x0a, 0x04, 0x63, 0x6f, 0x70, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, + 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x70, 0x79, + 0x48, 0x00, 0x52, 0x04, 0x63, 0x6f, 0x70, 0x79, 0x12, 0x2e, 0x0a, 0x06, 0x6d, 0x6b, 0x66, 0x69, + 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, + 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x46, 0x69, 0x6c, 0x65, 0x48, 0x00, + 0x52, 0x06, 0x6d, 0x6b, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x6d, 0x6b, 0x64, 0x69, + 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6c, + 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x44, 0x69, 0x72, 0x48, 0x00, 0x52, 0x05, + 0x6d, 0x6b, 0x64, 0x69, 0x72, 0x12, 0x22, 0x0a, 0x02, 0x72, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x6d, 0x48, 0x00, 0x52, 0x02, 0x72, 0x6d, 0x12, 0x31, 0x0a, 0x07, 0x73, 0x79, 0x6d, + 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x62, 0x2e, + 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, + 0x6b, 0x48, 0x00, 0x52, 0x07, 0x73, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x42, 0x08, 0x0a, 0x06, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xde, 0x04, 0x0a, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x41, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x70, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x72, 0x63, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x72, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x64, + 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x74, 0x12, + 0x22, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, + 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x6f, 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x52, 0x05, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, + 0x77, 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, + 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x28, 0x0a, + 0x0f, 0x64, 0x69, 0x72, 0x43, 0x6f, 0x70, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, 0x72, 0x43, 0x6f, 0x70, 0x79, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x20, 0x61, 0x74, 0x74, 0x65, 0x6d, + 0x70, 0x74, 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, + 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x20, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, + 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x73, + 0x74, 0x50, 0x61, 0x74, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0d, 0x61, + 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, + 0x64, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x57, + 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x61, + 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, + 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, + 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x74, 0x65, + 0x72, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x78, + 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x18, 0x0d, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x61, 0x74, + 0x74, 0x65, 0x72, 0x6e, 0x73, 0x12, 0x46, 0x0a, 0x1e, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x52, + 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, + 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1e, 0x61, + 0x6c, 0x77, 0x61, 0x79, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x45, 0x78, 0x69, 0x73, + 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x18, 0x0a, + 0x07, 0x6d, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x6d, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x22, 0x90, 0x01, 0x0a, 0x10, 0x46, 0x69, 0x6c, 0x65, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, + 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, + 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x6f, 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x6e, 0x0a, 0x0c, 0x46, 0x69, - 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, - 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x46, - 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x6c, - 0x64, 0x63, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x22, 0x4e, 0x0a, 0x08, 0x43, 0x68, - 0x6f, 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x12, 0x1f, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, - 0x74, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, - 0x4f, 0x70, 0x74, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x53, 0x0a, 0x07, 0x55, 0x73, - 0x65, 0x72, 0x4f, 0x70, 0x74, 0x12, 0x2a, 0x0a, 0x06, 0x62, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x64, - 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x48, 0x00, 0x52, 0x06, 0x62, 0x79, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x14, 0x0a, 0x04, 0x62, 0x79, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x48, - 0x00, 0x52, 0x04, 0x62, 0x79, 0x49, 0x44, 0x42, 0x06, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, - 0x38, 0x0a, 0x0c, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x22, 0x0a, 0x0a, 0x4d, 0x65, 0x72, - 0x67, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x31, 0x0a, - 0x07, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x4f, 0x70, 0x12, 0x26, 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, - 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x4d, 0x65, - 0x72, 0x67, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, - 0x22, 0x26, 0x0a, 0x0e, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, - 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x26, 0x0a, 0x0e, 0x55, 0x70, 0x70, 0x65, - 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, - 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, - 0x22, 0x5c, 0x0a, 0x06, 0x44, 0x69, 0x66, 0x66, 0x4f, 0x70, 0x12, 0x28, 0x0a, 0x05, 0x6c, 0x6f, - 0x77, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x4c, - 0x6f, 0x77, 0x65, 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x05, 0x6c, - 0x6f, 0x77, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x05, 0x75, 0x70, 0x70, 0x65, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x70, 0x65, 0x72, 0x44, 0x69, - 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x05, 0x75, 0x70, 0x70, 0x65, 0x72, 0x2a, 0x28, - 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x4e, 0x53, - 0x45, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x01, 0x12, 0x08, - 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x02, 0x2a, 0x29, 0x0a, 0x0c, 0x53, 0x65, 0x63, 0x75, - 0x72, 0x69, 0x74, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x41, 0x4e, 0x44, - 0x42, 0x4f, 0x58, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4e, 0x53, 0x45, 0x43, 0x55, 0x52, - 0x45, 0x10, 0x01, 0x2a, 0x40, 0x0a, 0x09, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x08, 0x0a, 0x04, 0x42, 0x49, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x45, - 0x43, 0x52, 0x45, 0x54, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x53, 0x48, 0x10, 0x02, 0x12, - 0x09, 0x0a, 0x05, 0x43, 0x41, 0x43, 0x48, 0x45, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x4d, - 0x50, 0x46, 0x53, 0x10, 0x04, 0x2a, 0x31, 0x0a, 0x11, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, - 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x4e, 0x10, 0x01, 0x12, - 0x07, 0x0a, 0x03, 0x4f, 0x46, 0x46, 0x10, 0x02, 0x2a, 0x36, 0x0a, 0x0f, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4f, 0x70, 0x74, 0x12, 0x0a, 0x0a, 0x06, 0x53, - 0x48, 0x41, 0x52, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x49, 0x56, 0x41, - 0x54, 0x45, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x02, - 0x42, 0x24, 0x5a, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, - 0x6f, 0x62, 0x79, 0x2f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2f, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x72, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x89, 0x01, 0x0a, 0x11, 0x46, + 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, + 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x6c, 0x64, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6f, 0x6c, 0x64, 0x70, 0x61, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, + 0x77, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x77, + 0x70, 0x61, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x6f, 0x77, 0x6e, 0x4f, 0x70, + 0x74, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x9d, 0x01, 0x0a, 0x0f, 0x46, 0x69, 0x6c, 0x65, 0x41, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x44, 0x69, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, + 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, + 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x6d, 0x6f, + 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x61, 0x6b, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6d, 0x61, 0x6b, 0x65, 0x50, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x6f, 0x77, 0x6e, 0x4f, 0x70, + 0x74, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x6e, 0x0a, 0x0c, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, + 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x69, + 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x22, 0x4e, 0x0a, 0x08, 0x43, 0x68, 0x6f, 0x77, 0x6e, 0x4f, + 0x70, 0x74, 0x12, 0x1f, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x52, 0x04, 0x75, + 0x73, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x52, + 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x53, 0x0a, 0x07, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, + 0x74, 0x12, 0x2a, 0x0a, 0x06, 0x62, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, + 0x4f, 0x70, 0x74, 0x48, 0x00, 0x52, 0x06, 0x62, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, + 0x04, 0x62, 0x79, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x04, 0x62, + 0x79, 0x49, 0x44, 0x42, 0x06, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x38, 0x0a, 0x0c, 0x4e, + 0x61, 0x6d, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, + 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x22, 0x0a, 0x0a, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x49, 0x6e, + 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x31, 0x0a, 0x07, 0x4d, 0x65, 0x72, + 0x67, 0x65, 0x4f, 0x70, 0x12, 0x26, 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x49, + 0x6e, 0x70, 0x75, 0x74, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x22, 0x26, 0x0a, 0x0e, + 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, + 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, + 0x6e, 0x70, 0x75, 0x74, 0x22, 0x26, 0x0a, 0x0e, 0x55, 0x70, 0x70, 0x65, 0x72, 0x44, 0x69, 0x66, + 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x5c, 0x0a, 0x06, + 0x44, 0x69, 0x66, 0x66, 0x4f, 0x70, 0x12, 0x28, 0x0a, 0x05, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x6f, 0x77, 0x65, 0x72, + 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x05, 0x6c, 0x6f, 0x77, 0x65, 0x72, + 0x12, 0x28, 0x0a, 0x05, 0x75, 0x70, 0x70, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x70, 0x65, 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, + 0x70, 0x75, 0x74, 0x52, 0x05, 0x75, 0x70, 0x70, 0x65, 0x72, 0x2a, 0x28, 0x0a, 0x07, 0x4e, 0x65, + 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x4e, 0x53, 0x45, 0x54, 0x10, 0x00, + 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, + 0x4e, 0x45, 0x10, 0x02, 0x2a, 0x29, 0x0a, 0x0c, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x41, 0x4e, 0x44, 0x42, 0x4f, 0x58, 0x10, + 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4e, 0x53, 0x45, 0x43, 0x55, 0x52, 0x45, 0x10, 0x01, 0x2a, + 0x40, 0x0a, 0x09, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, + 0x42, 0x49, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x45, 0x43, 0x52, 0x45, 0x54, + 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x53, 0x48, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x43, + 0x41, 0x43, 0x48, 0x45, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x4d, 0x50, 0x46, 0x53, 0x10, + 0x04, 0x2a, 0x31, 0x0a, 0x11, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, + 0x54, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x4f, + 0x46, 0x46, 0x10, 0x02, 0x2a, 0x36, 0x0a, 0x0f, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x68, 0x61, + 0x72, 0x69, 0x6e, 0x67, 0x4f, 0x70, 0x74, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x48, 0x41, 0x52, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x01, + 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x02, 0x42, 0x24, 0x5a, 0x22, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x6f, 0x62, 0x79, 0x2f, + 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2f, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2f, + 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3756,7 +3828,7 @@ func file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP() []byte { } var file_github_com_moby_buildkit_solver_pb_ops_proto_enumTypes = make([]protoimpl.EnumInfo, 5) -var file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes = make([]protoimpl.MessageInfo, 50) +var file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes = make([]protoimpl.MessageInfo, 51) var file_github_com_moby_buildkit_solver_pb_ops_proto_goTypes = []any{ (NetMode)(0), // 0: pb.NetMode (SecurityMode)(0), // 1: pb.SecurityMode @@ -3771,115 +3843,117 @@ var file_github_com_moby_buildkit_solver_pb_ops_proto_goTypes = []any{ (*HostIP)(nil), // 10: pb.HostIP (*Ulimit)(nil), // 11: pb.Ulimit (*SecretEnv)(nil), // 12: pb.SecretEnv - (*Mount)(nil), // 13: pb.Mount - (*TmpfsOpt)(nil), // 14: pb.TmpfsOpt - (*CacheOpt)(nil), // 15: pb.CacheOpt - (*SecretOpt)(nil), // 16: pb.SecretOpt - (*SSHOpt)(nil), // 17: pb.SSHOpt - (*SourceOp)(nil), // 18: pb.SourceOp - (*BuildOp)(nil), // 19: pb.BuildOp - (*BuildInput)(nil), // 20: pb.BuildInput - (*OpMetadata)(nil), // 21: pb.OpMetadata - (*Source)(nil), // 22: pb.Source - (*Locations)(nil), // 23: pb.Locations - (*SourceInfo)(nil), // 24: pb.SourceInfo - (*Location)(nil), // 25: pb.Location - (*Range)(nil), // 26: pb.Range - (*Position)(nil), // 27: pb.Position - (*ExportCache)(nil), // 28: pb.ExportCache - (*ProgressGroup)(nil), // 29: pb.ProgressGroup - (*ProxyEnv)(nil), // 30: pb.ProxyEnv - (*WorkerConstraints)(nil), // 31: pb.WorkerConstraints - (*Definition)(nil), // 32: pb.Definition - (*FileOp)(nil), // 33: pb.FileOp - (*FileAction)(nil), // 34: pb.FileAction - (*FileActionCopy)(nil), // 35: pb.FileActionCopy - (*FileActionMkFile)(nil), // 36: pb.FileActionMkFile - (*FileActionSymlink)(nil), // 37: pb.FileActionSymlink - (*FileActionMkDir)(nil), // 38: pb.FileActionMkDir - (*FileActionRm)(nil), // 39: pb.FileActionRm - (*ChownOpt)(nil), // 40: pb.ChownOpt - (*UserOpt)(nil), // 41: pb.UserOpt - (*NamedUserOpt)(nil), // 42: pb.NamedUserOpt - (*MergeInput)(nil), // 43: pb.MergeInput - (*MergeOp)(nil), // 44: pb.MergeOp - (*LowerDiffInput)(nil), // 45: pb.LowerDiffInput - (*UpperDiffInput)(nil), // 46: pb.UpperDiffInput - (*DiffOp)(nil), // 47: pb.DiffOp - nil, // 48: pb.SourceOp.AttrsEntry - nil, // 49: pb.BuildOp.InputsEntry - nil, // 50: pb.BuildOp.AttrsEntry - nil, // 51: pb.OpMetadata.DescriptionEntry - nil, // 52: pb.OpMetadata.CapsEntry - nil, // 53: pb.Source.LocationsEntry - nil, // 54: pb.Definition.MetadataEntry + (*CDIDevice)(nil), // 13: pb.CDIDevice + (*Mount)(nil), // 14: pb.Mount + (*TmpfsOpt)(nil), // 15: pb.TmpfsOpt + (*CacheOpt)(nil), // 16: pb.CacheOpt + (*SecretOpt)(nil), // 17: pb.SecretOpt + (*SSHOpt)(nil), // 18: pb.SSHOpt + (*SourceOp)(nil), // 19: pb.SourceOp + (*BuildOp)(nil), // 20: pb.BuildOp + (*BuildInput)(nil), // 21: pb.BuildInput + (*OpMetadata)(nil), // 22: pb.OpMetadata + (*Source)(nil), // 23: pb.Source + (*Locations)(nil), // 24: pb.Locations + (*SourceInfo)(nil), // 25: pb.SourceInfo + (*Location)(nil), // 26: pb.Location + (*Range)(nil), // 27: pb.Range + (*Position)(nil), // 28: pb.Position + (*ExportCache)(nil), // 29: pb.ExportCache + (*ProgressGroup)(nil), // 30: pb.ProgressGroup + (*ProxyEnv)(nil), // 31: pb.ProxyEnv + (*WorkerConstraints)(nil), // 32: pb.WorkerConstraints + (*Definition)(nil), // 33: pb.Definition + (*FileOp)(nil), // 34: pb.FileOp + (*FileAction)(nil), // 35: pb.FileAction + (*FileActionCopy)(nil), // 36: pb.FileActionCopy + (*FileActionMkFile)(nil), // 37: pb.FileActionMkFile + (*FileActionSymlink)(nil), // 38: pb.FileActionSymlink + (*FileActionMkDir)(nil), // 39: pb.FileActionMkDir + (*FileActionRm)(nil), // 40: pb.FileActionRm + (*ChownOpt)(nil), // 41: pb.ChownOpt + (*UserOpt)(nil), // 42: pb.UserOpt + (*NamedUserOpt)(nil), // 43: pb.NamedUserOpt + (*MergeInput)(nil), // 44: pb.MergeInput + (*MergeOp)(nil), // 45: pb.MergeOp + (*LowerDiffInput)(nil), // 46: pb.LowerDiffInput + (*UpperDiffInput)(nil), // 47: pb.UpperDiffInput + (*DiffOp)(nil), // 48: pb.DiffOp + nil, // 49: pb.SourceOp.AttrsEntry + nil, // 50: pb.BuildOp.InputsEntry + nil, // 51: pb.BuildOp.AttrsEntry + nil, // 52: pb.OpMetadata.DescriptionEntry + nil, // 53: pb.OpMetadata.CapsEntry + nil, // 54: pb.Source.LocationsEntry + nil, // 55: pb.Definition.MetadataEntry } var file_github_com_moby_buildkit_solver_pb_ops_proto_depIdxs = []int32{ 7, // 0: pb.Op.inputs:type_name -> pb.Input 8, // 1: pb.Op.exec:type_name -> pb.ExecOp - 18, // 2: pb.Op.source:type_name -> pb.SourceOp - 33, // 3: pb.Op.file:type_name -> pb.FileOp - 19, // 4: pb.Op.build:type_name -> pb.BuildOp - 44, // 5: pb.Op.merge:type_name -> pb.MergeOp - 47, // 6: pb.Op.diff:type_name -> pb.DiffOp + 19, // 2: pb.Op.source:type_name -> pb.SourceOp + 34, // 3: pb.Op.file:type_name -> pb.FileOp + 20, // 4: pb.Op.build:type_name -> pb.BuildOp + 45, // 5: pb.Op.merge:type_name -> pb.MergeOp + 48, // 6: pb.Op.diff:type_name -> pb.DiffOp 6, // 7: pb.Op.platform:type_name -> pb.Platform - 31, // 8: pb.Op.constraints:type_name -> pb.WorkerConstraints + 32, // 8: pb.Op.constraints:type_name -> pb.WorkerConstraints 9, // 9: pb.ExecOp.meta:type_name -> pb.Meta - 13, // 10: pb.ExecOp.mounts:type_name -> pb.Mount + 14, // 10: pb.ExecOp.mounts:type_name -> pb.Mount 0, // 11: pb.ExecOp.network:type_name -> pb.NetMode 1, // 12: pb.ExecOp.security:type_name -> pb.SecurityMode 12, // 13: pb.ExecOp.secretenv:type_name -> pb.SecretEnv - 30, // 14: pb.Meta.proxy_env:type_name -> pb.ProxyEnv - 10, // 15: pb.Meta.extraHosts:type_name -> pb.HostIP - 11, // 16: pb.Meta.ulimit:type_name -> pb.Ulimit - 2, // 17: pb.Mount.mountType:type_name -> pb.MountType - 14, // 18: pb.Mount.TmpfsOpt:type_name -> pb.TmpfsOpt - 15, // 19: pb.Mount.cacheOpt:type_name -> pb.CacheOpt - 16, // 20: pb.Mount.secretOpt:type_name -> pb.SecretOpt - 17, // 21: pb.Mount.SSHOpt:type_name -> pb.SSHOpt - 3, // 22: pb.Mount.contentCache:type_name -> pb.MountContentCache - 4, // 23: pb.CacheOpt.sharing:type_name -> pb.CacheSharingOpt - 48, // 24: pb.SourceOp.attrs:type_name -> pb.SourceOp.AttrsEntry - 49, // 25: pb.BuildOp.inputs:type_name -> pb.BuildOp.InputsEntry - 32, // 26: pb.BuildOp.def:type_name -> pb.Definition - 50, // 27: pb.BuildOp.attrs:type_name -> pb.BuildOp.AttrsEntry - 51, // 28: pb.OpMetadata.description:type_name -> pb.OpMetadata.DescriptionEntry - 28, // 29: pb.OpMetadata.export_cache:type_name -> pb.ExportCache - 52, // 30: pb.OpMetadata.caps:type_name -> pb.OpMetadata.CapsEntry - 29, // 31: pb.OpMetadata.progress_group:type_name -> pb.ProgressGroup - 53, // 32: pb.Source.locations:type_name -> pb.Source.LocationsEntry - 24, // 33: pb.Source.infos:type_name -> pb.SourceInfo - 25, // 34: pb.Locations.locations:type_name -> pb.Location - 32, // 35: pb.SourceInfo.definition:type_name -> pb.Definition - 26, // 36: pb.Location.ranges:type_name -> pb.Range - 27, // 37: pb.Range.start:type_name -> pb.Position - 27, // 38: pb.Range.end:type_name -> pb.Position - 54, // 39: pb.Definition.metadata:type_name -> pb.Definition.MetadataEntry - 22, // 40: pb.Definition.Source:type_name -> pb.Source - 34, // 41: pb.FileOp.actions:type_name -> pb.FileAction - 35, // 42: pb.FileAction.copy:type_name -> pb.FileActionCopy - 36, // 43: pb.FileAction.mkfile:type_name -> pb.FileActionMkFile - 38, // 44: pb.FileAction.mkdir:type_name -> pb.FileActionMkDir - 39, // 45: pb.FileAction.rm:type_name -> pb.FileActionRm - 37, // 46: pb.FileAction.symlink:type_name -> pb.FileActionSymlink - 40, // 47: pb.FileActionCopy.owner:type_name -> pb.ChownOpt - 40, // 48: pb.FileActionMkFile.owner:type_name -> pb.ChownOpt - 40, // 49: pb.FileActionSymlink.owner:type_name -> pb.ChownOpt - 40, // 50: pb.FileActionMkDir.owner:type_name -> pb.ChownOpt - 41, // 51: pb.ChownOpt.user:type_name -> pb.UserOpt - 41, // 52: pb.ChownOpt.group:type_name -> pb.UserOpt - 42, // 53: pb.UserOpt.byName:type_name -> pb.NamedUserOpt - 43, // 54: pb.MergeOp.inputs:type_name -> pb.MergeInput - 45, // 55: pb.DiffOp.lower:type_name -> pb.LowerDiffInput - 46, // 56: pb.DiffOp.upper:type_name -> pb.UpperDiffInput - 20, // 57: pb.BuildOp.InputsEntry.value:type_name -> pb.BuildInput - 23, // 58: pb.Source.LocationsEntry.value:type_name -> pb.Locations - 21, // 59: pb.Definition.MetadataEntry.value:type_name -> pb.OpMetadata - 60, // [60:60] is the sub-list for method output_type - 60, // [60:60] is the sub-list for method input_type - 60, // [60:60] is the sub-list for extension type_name - 60, // [60:60] is the sub-list for extension extendee - 0, // [0:60] is the sub-list for field type_name + 13, // 14: pb.ExecOp.cdiDevices:type_name -> pb.CDIDevice + 31, // 15: pb.Meta.proxy_env:type_name -> pb.ProxyEnv + 10, // 16: pb.Meta.extraHosts:type_name -> pb.HostIP + 11, // 17: pb.Meta.ulimit:type_name -> pb.Ulimit + 2, // 18: pb.Mount.mountType:type_name -> pb.MountType + 15, // 19: pb.Mount.TmpfsOpt:type_name -> pb.TmpfsOpt + 16, // 20: pb.Mount.cacheOpt:type_name -> pb.CacheOpt + 17, // 21: pb.Mount.secretOpt:type_name -> pb.SecretOpt + 18, // 22: pb.Mount.SSHOpt:type_name -> pb.SSHOpt + 3, // 23: pb.Mount.contentCache:type_name -> pb.MountContentCache + 4, // 24: pb.CacheOpt.sharing:type_name -> pb.CacheSharingOpt + 49, // 25: pb.SourceOp.attrs:type_name -> pb.SourceOp.AttrsEntry + 50, // 26: pb.BuildOp.inputs:type_name -> pb.BuildOp.InputsEntry + 33, // 27: pb.BuildOp.def:type_name -> pb.Definition + 51, // 28: pb.BuildOp.attrs:type_name -> pb.BuildOp.AttrsEntry + 52, // 29: pb.OpMetadata.description:type_name -> pb.OpMetadata.DescriptionEntry + 29, // 30: pb.OpMetadata.export_cache:type_name -> pb.ExportCache + 53, // 31: pb.OpMetadata.caps:type_name -> pb.OpMetadata.CapsEntry + 30, // 32: pb.OpMetadata.progress_group:type_name -> pb.ProgressGroup + 54, // 33: pb.Source.locations:type_name -> pb.Source.LocationsEntry + 25, // 34: pb.Source.infos:type_name -> pb.SourceInfo + 26, // 35: pb.Locations.locations:type_name -> pb.Location + 33, // 36: pb.SourceInfo.definition:type_name -> pb.Definition + 27, // 37: pb.Location.ranges:type_name -> pb.Range + 28, // 38: pb.Range.start:type_name -> pb.Position + 28, // 39: pb.Range.end:type_name -> pb.Position + 55, // 40: pb.Definition.metadata:type_name -> pb.Definition.MetadataEntry + 23, // 41: pb.Definition.Source:type_name -> pb.Source + 35, // 42: pb.FileOp.actions:type_name -> pb.FileAction + 36, // 43: pb.FileAction.copy:type_name -> pb.FileActionCopy + 37, // 44: pb.FileAction.mkfile:type_name -> pb.FileActionMkFile + 39, // 45: pb.FileAction.mkdir:type_name -> pb.FileActionMkDir + 40, // 46: pb.FileAction.rm:type_name -> pb.FileActionRm + 38, // 47: pb.FileAction.symlink:type_name -> pb.FileActionSymlink + 41, // 48: pb.FileActionCopy.owner:type_name -> pb.ChownOpt + 41, // 49: pb.FileActionMkFile.owner:type_name -> pb.ChownOpt + 41, // 50: pb.FileActionSymlink.owner:type_name -> pb.ChownOpt + 41, // 51: pb.FileActionMkDir.owner:type_name -> pb.ChownOpt + 42, // 52: pb.ChownOpt.user:type_name -> pb.UserOpt + 42, // 53: pb.ChownOpt.group:type_name -> pb.UserOpt + 43, // 54: pb.UserOpt.byName:type_name -> pb.NamedUserOpt + 44, // 55: pb.MergeOp.inputs:type_name -> pb.MergeInput + 46, // 56: pb.DiffOp.lower:type_name -> pb.LowerDiffInput + 47, // 57: pb.DiffOp.upper:type_name -> pb.UpperDiffInput + 21, // 58: pb.BuildOp.InputsEntry.value:type_name -> pb.BuildInput + 24, // 59: pb.Source.LocationsEntry.value:type_name -> pb.Locations + 22, // 60: pb.Definition.MetadataEntry.value:type_name -> pb.OpMetadata + 61, // [61:61] is the sub-list for method output_type + 61, // [61:61] is the sub-list for method input_type + 61, // [61:61] is the sub-list for extension type_name + 61, // [61:61] is the sub-list for extension extendee + 0, // [0:61] is the sub-list for field type_name } func init() { file_github_com_moby_buildkit_solver_pb_ops_proto_init() } @@ -3895,14 +3969,14 @@ func file_github_com_moby_buildkit_solver_pb_ops_proto_init() { (*Op_Merge)(nil), (*Op_Diff)(nil), } - file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[29].OneofWrappers = []any{ + file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[30].OneofWrappers = []any{ (*FileAction_Copy)(nil), (*FileAction_Mkfile)(nil), (*FileAction_Mkdir)(nil), (*FileAction_Rm)(nil), (*FileAction_Symlink)(nil), } - file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[36].OneofWrappers = []any{ + file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[37].OneofWrappers = []any{ (*UserOpt_ByName)(nil), (*UserOpt_ByID)(nil), } @@ -3912,7 +3986,7 @@ func file_github_com_moby_buildkit_solver_pb_ops_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_github_com_moby_buildkit_solver_pb_ops_proto_rawDesc, NumEnums: 5, - NumMessages: 50, + NumMessages: 51, NumExtensions: 0, NumServices: 0, }, diff --git a/solver/pb/ops.proto b/solver/pb/ops.proto index 5ff388299cef..90b69560e005 100644 --- a/solver/pb/ops.proto +++ b/solver/pb/ops.proto @@ -47,6 +47,7 @@ message ExecOp { NetMode network = 3; SecurityMode security = 4; repeated SecretEnv secretenv = 5; + repeated CDIDevice cdiDevices = 6; } // Meta is a set of arguments for ExecOp. @@ -95,6 +96,15 @@ message SecretEnv { bool optional = 3; } +// CDIDevice specifies a CDI device information. +message CDIDevice { + // Fully qualified CDI device name (e.g., vendor.com/gpu=gpudevice1) + // https://github.com/cncf-tags/container-device-interface/blob/main/SPEC.md + string name = 1; + // Optional defines if CDI device is required. + bool optional = 2; +} + // Mount specifies how to mount an input Op as a filesystem. message Mount { int64 input = 1; diff --git a/solver/pb/ops_vtproto.pb.go b/solver/pb/ops_vtproto.pb.go index 9d71812423f7..1a6c89c3690f 100644 --- a/solver/pb/ops_vtproto.pb.go +++ b/solver/pb/ops_vtproto.pb.go @@ -166,6 +166,13 @@ func (m *ExecOp) CloneVT() *ExecOp { } r.Secretenv = tmpContainer } + if rhs := m.CdiDevices; rhs != nil { + tmpContainer := make([]*CDIDevice, len(rhs)) + for k, v := range rhs { + tmpContainer[k] = v.CloneVT() + } + r.CdiDevices = tmpContainer + } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) copy(r.unknownFields, m.unknownFields) @@ -284,6 +291,24 @@ func (m *SecretEnv) CloneMessageVT() proto.Message { return m.CloneVT() } +func (m *CDIDevice) CloneVT() *CDIDevice { + if m == nil { + return (*CDIDevice)(nil) + } + r := new(CDIDevice) + r.Name = m.Name + r.Optional = m.Optional + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *CDIDevice) CloneMessageVT() proto.Message { + return m.CloneVT() +} + func (m *Mount) CloneVT() *Mount { if m == nil { return (*Mount)(nil) @@ -1429,6 +1454,23 @@ func (this *ExecOp) EqualVT(that *ExecOp) bool { } } } + if len(this.CdiDevices) != len(that.CdiDevices) { + return false + } + for i, vx := range this.CdiDevices { + vy := that.CdiDevices[i] + if p, q := vx, vy; p != q { + if p == nil { + p = &CDIDevice{} + } + if q == nil { + q = &CDIDevice{} + } + if !p.EqualVT(q) { + return false + } + } + } return string(this.unknownFields) == string(that.unknownFields) } @@ -1606,6 +1648,28 @@ func (this *SecretEnv) EqualMessageVT(thatMsg proto.Message) bool { } return this.EqualVT(that) } +func (this *CDIDevice) EqualVT(that *CDIDevice) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if this.Name != that.Name { + return false + } + if this.Optional != that.Optional { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *CDIDevice) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*CDIDevice) + if !ok { + return false + } + return this.EqualVT(that) +} func (this *Mount) EqualVT(that *Mount) bool { if this == that { return true @@ -3220,6 +3284,18 @@ func (m *ExecOp) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.CdiDevices) > 0 { + for iNdEx := len(m.CdiDevices) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.CdiDevices[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x32 + } + } if len(m.Secretenv) > 0 { for iNdEx := len(m.Secretenv) - 1; iNdEx >= 0; iNdEx-- { size, err := m.Secretenv[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) @@ -3565,6 +3641,56 @@ func (m *SecretEnv) MarshalToSizedBufferVT(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *CDIDevice) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CDIDevice) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *CDIDevice) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Optional { + i-- + if m.Optional { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *Mount) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -6023,6 +6149,12 @@ func (m *ExecOp) SizeVT() (n int) { n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } } + if len(m.CdiDevices) > 0 { + for _, e := range m.CdiDevices { + l = e.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } n += len(m.unknownFields) return n } @@ -6150,6 +6282,23 @@ func (m *SecretEnv) SizeVT() (n int) { return n } +func (m *CDIDevice) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Optional { + n += 2 + } + n += len(m.unknownFields) + return n +} + func (m *Mount) SizeVT() (n int) { if m == nil { return 0 @@ -7936,6 +8085,40 @@ func (m *ExecOp) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CdiDevices", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CdiDevices = append(m.CdiDevices, &CDIDevice{}) + if err := m.CdiDevices[len(m.CdiDevices)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) @@ -8772,6 +8955,109 @@ func (m *SecretEnv) UnmarshalVT(dAtA []byte) error { } return nil } +func (m *CDIDevice) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CDIDevice: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CDIDevice: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Optional", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Optional = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *Mount) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/solver/progress.go b/solver/progress.go index 92e2c6cb009f..dfc01b801e44 100644 --- a/solver/progress.go +++ b/solver/progress.go @@ -60,7 +60,9 @@ func (j *Job) Status(ctx context.Context, ch chan *client.SolveStatus) error { bklog.G(ctx).Warnf("progress %s log without vertex info", p.ID) continue } - v.Vertex = vtx.(digest.Digest) + if v.Vertex == "" { + v.Vertex = vtx.(digest.Digest) + } v.Timestamp = p.Timestamp ss.Logs = append(ss.Logs, &v) case client.VertexWarning: @@ -69,7 +71,9 @@ func (j *Job) Status(ctx context.Context, ch chan *client.SolveStatus) error { bklog.G(ctx).Warnf("progress %s warning without vertex info", p.ID) continue } - v.Vertex = vtx.(digest.Digest) + if v.Vertex == "" { + v.Vertex = vtx.(digest.Digest) + } ss.Warnings = append(ss.Warnings, &v) } } diff --git a/util/appdefaults/appdefaults_unix.go b/util/appdefaults/appdefaults_unix.go index cb1aa06d18a2..a351a7944e85 100644 --- a/util/appdefaults/appdefaults_unix.go +++ b/util/appdefaults/appdefaults_unix.go @@ -17,6 +17,7 @@ const ( var ( UserCNIConfigPath = filepath.Join(UserConfigDir(), "cni.json") + CDISpecDirs = []string{"/etc/cdi", "/var/run/cdi", "/etc/buildkit/cdi"} ) // UserAddress typically returns /run/user/$UID/buildkit/buildkitd.sock diff --git a/util/appdefaults/appdefaults_windows.go b/util/appdefaults/appdefaults_windows.go index 323c8a98abf9..c2103887a341 100644 --- a/util/appdefaults/appdefaults_windows.go +++ b/util/appdefaults/appdefaults_windows.go @@ -18,6 +18,7 @@ var ( var ( UserCNIConfigPath = DefaultCNIConfigPath + CDISpecDirs []string ) func UserAddress() string { diff --git a/util/testutil/integration/run.go b/util/testutil/integration/run.go index 4dbbcf229c9b..2c08102914ac 100644 --- a/util/testutil/integration/run.go +++ b/util/testutil/integration/run.go @@ -60,12 +60,14 @@ type Sandbox interface { NewRegistry() (string, error) Value(string) interface{} // chosen matrix value Name() string + CDISpecDir() string } // BackendConfig is used to configure backends created by a worker. type BackendConfig struct { Logs map[string]*bytes.Buffer DaemonConfig []ConfigUpdater + CDISpecDir string } type Worker interface { diff --git a/util/testutil/integration/sandbox.go b/util/testutil/integration/sandbox.go index f28fbf1765dc..76c5e110b577 100644 --- a/util/testutil/integration/sandbox.go +++ b/util/testutil/integration/sandbox.go @@ -27,11 +27,12 @@ const maxSandboxTimeout = 5 * time.Minute type sandbox struct { Backend - logs map[string]*bytes.Buffer - cleanup *MultiCloser - mv matrixValue - ctx context.Context - name string + logs map[string]*bytes.Buffer + cleanup *MultiCloser + mv matrixValue + ctx context.Context + cdiSpecDir string + name string } func (sb *sandbox) Name() string { @@ -42,6 +43,10 @@ func (sb *sandbox) Context() context.Context { return sb.ctx } +func (sb *sandbox) CDISpecDir() string { + return sb.cdiSpecDir +} + func (sb *sandbox) Logs() map[string]*bytes.Buffer { return sb.logs } @@ -110,6 +115,15 @@ func newSandbox(ctx context.Context, t *testing.T, w Worker, mirror string, mv m } }() + cdiSpecDir, err := os.MkdirTemp("", "buildkit-integration-cdi") + if err != nil { + return nil, nil, errors.Wrap(err, "cannot create cdi spec dir") + } + deferF.Append(func() error { + return os.RemoveAll(cdiSpecDir) + }) + cfg.CDISpecDir = cdiSpecDir + b, closer, err := w.New(ctx, cfg) if err != nil { return nil, nil, errors.Wrap(err, "creating worker") @@ -139,12 +153,13 @@ func newSandbox(ctx context.Context, t *testing.T, w Worker, mirror string, mv m }() return &sandbox{ - Backend: b, - logs: cfg.Logs, - cleanup: deferF, - mv: mv, - ctx: ctx, - name: w.Name(), + Backend: b, + logs: cfg.Logs, + cleanup: deferF, + mv: mv, + ctx: ctx, + cdiSpecDir: cfg.CDISpecDir, + name: w.Name(), }, cl, nil } diff --git a/util/testutil/workers/containerd.go b/util/testutil/workers/containerd.go index d73e5dd89a41..b0c9e918b8a9 100644 --- a/util/testutil/workers/containerd.go +++ b/util/testutil/workers/containerd.go @@ -212,6 +212,7 @@ disabled_plugins = ["io.containerd.grpc.v1.cri"] "--containerd-worker=true", "--containerd-worker-addr", address, "--containerd-worker-labels=org.mobyproject.buildkit.worker.sandbox=true", // Include use of --containerd-worker-labels to trigger https://github.com/moby/buildkit/pull/603 + "--cdi-spec-dir=" + cfg.CDISpecDir, } buildkitdArgs = applyBuildkitdPlatformFlags(buildkitdArgs) buildkitdArgs = append(buildkitdArgs, snBuildkitdArgs...) diff --git a/util/testutil/workers/oci.go b/util/testutil/workers/oci.go index 54eefd130d99..5810a040dbe2 100644 --- a/util/testutil/workers/oci.go +++ b/util/testutil/workers/oci.go @@ -47,7 +47,13 @@ func (s *OCI) New(ctx context.Context, cfg *integration.BackendConfig) (integrat return nil, nil, err } // Include use of --oci-worker-labels to trigger https://github.com/moby/buildkit/pull/603 - buildkitdArgs := []string{"buildkitd", "--oci-worker=true", "--containerd-worker=false", "--oci-worker-gc=false", "--oci-worker-labels=org.mobyproject.buildkit.worker.sandbox=true"} + buildkitdArgs := []string{"buildkitd", + "--oci-worker=true", + "--containerd-worker=false", + "--oci-worker-gc=false", + "--oci-worker-labels=org.mobyproject.buildkit.worker.sandbox=true", + "--cdi-spec-dir=" + cfg.CDISpecDir, + } if s.Snapshotter != "" { buildkitdArgs = append(buildkitdArgs, diff --git a/worker/base/worker.go b/worker/base/worker.go index ffe78f6ec6b1..c1569cd98a1e 100644 --- a/worker/base/worker.go +++ b/worker/base/worker.go @@ -33,6 +33,7 @@ import ( containerdsnapshot "github.com/moby/buildkit/snapshot/containerd" "github.com/moby/buildkit/snapshot/imagerefchecker" "github.com/moby/buildkit/solver" + "github.com/moby/buildkit/solver/llbsolver/cdidevices" "github.com/moby/buildkit/solver/llbsolver/mounts" "github.com/moby/buildkit/solver/llbsolver/ops" "github.com/moby/buildkit/solver/pb" @@ -82,6 +83,7 @@ type WorkerOpt struct { MetadataStore *metadata.Store MountPoolRoot string ResourceMonitor *resources.Monitor + CDIManager *cdidevices.Manager } // Worker is a local worker instance with dedicated snapshotter, cache, and so on. @@ -245,6 +247,10 @@ func (w *Worker) LeaseManager() *leaseutil.Manager { return w.WorkerOpt.LeaseManager } +func (w *Worker) CDIManager() *cdidevices.Manager { + return w.WorkerOpt.CDIManager +} + func (w *Worker) ID() string { return w.WorkerOpt.ID } diff --git a/worker/containerd/containerd.go b/worker/containerd/containerd.go index 31f5e01b0341..c6a5b1e058f6 100644 --- a/worker/containerd/containerd.go +++ b/worker/containerd/containerd.go @@ -16,6 +16,7 @@ import ( "github.com/moby/buildkit/executor/containerdexecutor" "github.com/moby/buildkit/executor/oci" containerdsnapshot "github.com/moby/buildkit/snapshot/containerd" + "github.com/moby/buildkit/solver/llbsolver/cdidevices" "github.com/moby/buildkit/util/leaseutil" "github.com/moby/buildkit/util/network/netproviders" "github.com/moby/buildkit/util/winlayers" @@ -43,6 +44,7 @@ type WorkerOptions struct { ParallelismSem *semaphore.Weighted TraceSocket string Runtime *RuntimeInfo + CDIManager *cdidevices.Manager } // NewWorkerOpt creates a WorkerOpt. @@ -162,6 +164,7 @@ func newContainerd(client *ctd.Client, workerOpts WorkerOptions) (base.WorkerOpt TraceSocket: workerOpts.TraceSocket, Rootless: workerOpts.Rootless, Runtime: workerOpts.Runtime, + CDIManager: workerOpts.CDIManager, NetworkProviders: np, } @@ -182,6 +185,7 @@ func newContainerd(client *ctd.Client, workerOpts WorkerOptions) (base.WorkerOpt GarbageCollect: gc, ParallelismSem: workerOpts.ParallelismSem, MountPoolRoot: filepath.Join(root, "cachemounts"), + CDIManager: workerOpts.CDIManager, } return opt, nil } diff --git a/worker/runc/runc.go b/worker/runc/runc.go index bd39247d17f3..0ea36169bdd2 100644 --- a/worker/runc/runc.go +++ b/worker/runc/runc.go @@ -21,6 +21,7 @@ import ( "github.com/moby/buildkit/executor/resources" "github.com/moby/buildkit/executor/runcexecutor" containerdsnapshot "github.com/moby/buildkit/snapshot/containerd" + "github.com/moby/buildkit/solver/llbsolver/cdidevices" "github.com/moby/buildkit/util/leaseutil" "github.com/moby/buildkit/util/network/netproviders" "github.com/moby/buildkit/util/winlayers" @@ -29,6 +30,7 @@ import ( ocispecs "github.com/opencontainers/image-spec/specs-go/v1" bolt "go.etcd.io/bbolt" "golang.org/x/sync/semaphore" + "tags.cncf.io/container-device-interface/pkg/cdi" ) // SnapshotterFactory instantiates a snapshotter @@ -38,7 +40,7 @@ type SnapshotterFactory struct { } // NewWorkerOpt creates a WorkerOpt. -func NewWorkerOpt(root string, snFactory SnapshotterFactory, rootless bool, processMode oci.ProcessMode, labels map[string]string, idmap *idtools.IdentityMapping, nopt netproviders.Opt, dns *oci.DNSConfig, binary, apparmorProfile string, selinux bool, parallelismSem *semaphore.Weighted, traceSocket, defaultCgroupParent string) (base.WorkerOpt, error) { +func NewWorkerOpt(root string, snFactory SnapshotterFactory, rootless bool, processMode oci.ProcessMode, labels map[string]string, idmap *idtools.IdentityMapping, nopt netproviders.Opt, dns *oci.DNSConfig, binary, apparmorProfile string, selinux bool, parallelismSem *semaphore.Weighted, traceSocket, defaultCgroupParent string, cdiManager *cdi.Cache) (base.WorkerOpt, error) { var opt base.WorkerOpt name := "runc-" + snFactory.Name root = filepath.Join(root, name) @@ -78,6 +80,7 @@ func NewWorkerOpt(root string, snFactory SnapshotterFactory, rootless bool, proc TracingSocket: traceSocket, DefaultCgroupParent: defaultCgroupParent, ResourceMonitor: rm, + CDIManager: cdidevices.NewManager(cdiManager), }, np) if err != nil { return opt, err @@ -166,6 +169,7 @@ func NewWorkerOpt(root string, snFactory SnapshotterFactory, rootless bool, proc ParallelismSem: parallelismSem, MountPoolRoot: filepath.Join(root, "cachemounts"), ResourceMonitor: rm, + CDIManager: cdidevices.NewManager(cdiManager), } return opt, nil } diff --git a/worker/runc/runc_test.go b/worker/runc/runc_test.go index ed0835046e64..ea58b90d47f0 100644 --- a/worker/runc/runc_test.go +++ b/worker/runc/runc_test.go @@ -37,7 +37,7 @@ func newWorkerOpt(t *testing.T, processMode oci.ProcessMode) base.WorkerOpt { }, } rootless := false - workerOpt, err := NewWorkerOpt(tmpdir, snFactory, rootless, processMode, nil, nil, netproviders.Opt{Mode: "host"}, nil, "", "", false, nil, "", "") + workerOpt, err := NewWorkerOpt(tmpdir, snFactory, rootless, processMode, nil, nil, netproviders.Opt{Mode: "host"}, nil, "", "", false, nil, "", "", nil) require.NoError(t, err) return workerOpt diff --git a/worker/worker.go b/worker/worker.go index ca5292e9eced..0b5b4cd3b4f7 100644 --- a/worker/worker.go +++ b/worker/worker.go @@ -13,6 +13,7 @@ import ( "github.com/moby/buildkit/session" containerdsnapshot "github.com/moby/buildkit/snapshot/containerd" "github.com/moby/buildkit/solver" + "github.com/moby/buildkit/solver/llbsolver/cdidevices" "github.com/moby/buildkit/solver/pb" "github.com/moby/buildkit/util/leaseutil" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" @@ -41,6 +42,7 @@ type Worker interface { CacheManager() cache.Manager LeaseManager() *leaseutil.Manager GarbageCollect(context.Context) error + CDIManager() *cdidevices.Manager } type Infos interface {