diff --git a/cli/testdata/coder_provisioner_list_--output_json.golden b/cli/testdata/coder_provisioner_list_--output_json.golden index 73dd35ff84266..cfa777e99c3f9 100644 --- a/cli/testdata/coder_provisioner_list_--output_json.golden +++ b/cli/testdata/coder_provisioner_list_--output_json.golden @@ -7,7 +7,7 @@ "last_seen_at": "====[timestamp]=====", "name": "test-daemon", "version": "v0.0.0-devel", - "api_version": "1.6", + "api_version": "1.7", "provisioners": [ "echo" ], diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index 5bfa015af3d78..ee11b7ea95edf 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -171,7 +171,7 @@ var ( DisplayName: "Provisioner Daemon", Site: rbac.Permissions(map[string][]policy.Action{ rbac.ResourceProvisionerJobs.Type: {policy.ActionRead, policy.ActionUpdate, policy.ActionCreate}, - rbac.ResourceFile.Type: {policy.ActionRead}, + rbac.ResourceFile.Type: {policy.ActionCreate, policy.ActionRead}, rbac.ResourceSystem.Type: {policy.WildcardSymbol}, rbac.ResourceTemplate.Type: {policy.ActionRead, policy.ActionUpdate}, // Unsure why provisionerd needs update and read personal diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go index cc63844ce16a3..eba4b945f06e1 100644 --- a/coderd/database/dbmem/dbmem.go +++ b/coderd/database/dbmem/dbmem.go @@ -8743,6 +8743,12 @@ func (q *FakeQuerier) InsertFile(_ context.Context, arg database.InsertFileParam q.mutex.Lock() defer q.mutex.Unlock() + if slices.ContainsFunc(q.files, func(file database.File) bool { + return file.CreatedBy == arg.CreatedBy && file.Hash == arg.Hash + }) { + return database.File{}, newUniqueConstraintError(database.UniqueFilesHashCreatedByKey) + } + //nolint:gosimple file := database.File{ ID: arg.ID, diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go index 31165cf89f65b..b8cf6315a8e3f 100644 --- a/coderd/provisionerdserver/provisionerdserver.go +++ b/coderd/provisionerdserver/provisionerdserver.go @@ -773,7 +773,7 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo case database.ProvisionerStorageMethodFile: file, err := s.Database.GetFileByID(ctx, job.FileID) if err != nil { - return nil, failJob(fmt.Sprintf("get file by hash: %s", err)) + return nil, failJob(fmt.Sprintf("get file by id: %s", err)) } protoJob.TemplateSourceArchive = file.Data default: @@ -1321,6 +1321,104 @@ func (s *server) prepareForNotifyWorkspaceManualBuildFailed(ctx context.Context, return templateAdmins, template, templateVersion, workspaceOwner, nil } +func (s *server) UploadFile(stream proto.DRPCProvisionerDaemon_UploadFileStream) error { + var file *sdkproto.DataBuilder + // Always terminate the stream with an empty response. + defer stream.SendAndClose(&proto.Empty{}) + +UploadFileStream: + for { + msg, err := stream.Recv() + if err != nil { + return xerrors.Errorf("receive complete job with files: %w", err) + } + + switch typed := msg.Type.(type) { + case *proto.UploadFileRequest_DataUpload: + if file != nil { + return xerrors.New("unexpected file upload while waiting for file completion") + } + + file, err = sdkproto.NewDataBuilder(&sdkproto.DataUpload{ + UploadType: typed.DataUpload.UploadType, + DataHash: typed.DataUpload.DataHash, + FileSize: typed.DataUpload.FileSize, + Chunks: typed.DataUpload.Chunks, + }) + if err != nil { + return xerrors.Errorf("unable to create file upload: %w", err) + } + + if file.IsDone() { + // If a file is 0 bytes, we can consider it done immediately. + // This should never really happen in practice, but we handle it gracefully. + break UploadFileStream + } + case *proto.UploadFileRequest_ChunkPiece: + if file == nil { + return xerrors.New("unexpected chunk piece while waiting for file upload") + } + + done, err := file.Add(&sdkproto.ChunkPiece{ + Data: typed.ChunkPiece.Data, + FullDataHash: typed.ChunkPiece.FullDataHash, + PieceIndex: typed.ChunkPiece.PieceIndex, + }) + if err != nil { + return xerrors.Errorf("unable to add chunk piece: %w", err) + } + + if done { + break UploadFileStream + } + } + } + + fileData, err := file.Complete() + if err != nil { + return xerrors.Errorf("complete file upload: %w", err) + } + + // Just rehash the data to be sure it is correct. + hashBytes := sha256.Sum256(fileData) + hash := hex.EncodeToString(hashBytes[:]) + + var insert database.InsertFileParams + + switch file.Type { + case sdkproto.DataUploadType_UPLOAD_TYPE_MODULE_FILES: + insert = database.InsertFileParams{ + ID: uuid.New(), + Hash: hash, + CreatedAt: dbtime.Now(), + CreatedBy: uuid.Nil, + Mimetype: tarMimeType, + Data: fileData, + } + default: + return xerrors.Errorf("unsupported file upload type: %s", file.Type) + } + + //nolint:gocritic // Provisionerd actor + _, err = s.Database.InsertFile(dbauthz.AsProvisionerd(s.lifecycleCtx), insert) + if err != nil { + // Duplicated files already exist in the database, so we can ignore this error. + if !database.IsUniqueViolation(err, database.UniqueFilesHashCreatedByKey) { + return xerrors.Errorf("insert file: %w", err) + } + } + + s.Logger.Info(s.lifecycleCtx, "file uploaded to database", + slog.F("type", file.Type.String()), + slog.F("hash", hash), + slog.F("size", len(fileData)), + // new_insert indicates whether the file was newly inserted or already existed. + slog.F("new_insert", err == nil), + ) + + return nil +} + // CompleteJob is triggered by a provision daemon to mark a provisioner job as completed. func (s *server) CompleteJob(ctx context.Context, completed *proto.CompletedJob) (*proto.Empty, error) { ctx, span := s.startTrace(ctx, tracing.FuncName()) @@ -1606,6 +1704,20 @@ func (s *server) completeTemplateImportJob(ctx context.Context, job database.Pro } } + if len(jobType.TemplateImport.ModuleFilesHash) > 0 { + hashString := hex.EncodeToString(jobType.TemplateImport.ModuleFilesHash) + //nolint:gocritic // Acting as provisioner + file, err := db.GetFileByHashAndCreator(dbauthz.AsProvisionerd(ctx), database.GetFileByHashAndCreatorParams{Hash: hashString, CreatedBy: uuid.Nil}) + if err != nil { + return xerrors.Errorf("get file by hash, it should have been uploaded: %w", err) + } + + fileID = uuid.NullUUID{ + Valid: true, + UUID: file.ID, + } + } + err = db.InsertTemplateVersionTerraformValuesByJobID(ctx, database.InsertTemplateVersionTerraformValuesByJobIDParams{ JobID: jobID, UpdatedAt: now, diff --git a/coderd/provisionerdserver/upload_file_test.go b/coderd/provisionerdserver/upload_file_test.go new file mode 100644 index 0000000000000..3aaef1b02ea12 --- /dev/null +++ b/coderd/provisionerdserver/upload_file_test.go @@ -0,0 +1,191 @@ +package provisionerdserver_test + +import ( + "context" + crand "crypto/rand" + "fmt" + "testing" + + "github.com/google/uuid" + "github.com/stretchr/testify/require" + "golang.org/x/xerrors" + "storj.io/drpc" + + "github.com/coder/coder/v2/coderd/database" + "github.com/coder/coder/v2/coderd/externalauth" + "github.com/coder/coder/v2/codersdk/drpcsdk" + proto "github.com/coder/coder/v2/provisionerd/proto" + sdkproto "github.com/coder/coder/v2/provisionersdk/proto" + "github.com/coder/coder/v2/testutil" +) + +// TestUploadFileLargeModuleFiles tests the UploadFile RPC with large module files +func TestUploadFileLargeModuleFiles(t *testing.T) { + t.Parallel() + + ctx := testutil.Context(t, testutil.WaitMedium) + + // Create server + server, db, _, _ := setup(t, false, &overrides{ + externalAuthConfigs: []*externalauth.Config{{}}, + }) + + testSizes := []int{ + 0, // Empty file + 512, // A small file + drpcsdk.MaxMessageSize + 1024, // Just over the limit + drpcsdk.MaxMessageSize * 2, // 2x the limit + sdkproto.ChunkSize*3 + 512, // Multiple chunks with partial last + } + + for _, size := range testSizes { + t.Run(fmt.Sprintf("size_%d_bytes", size), func(t *testing.T) { + t.Parallel() + + // Generate test module files data + moduleData := make([]byte, size) + _, err := crand.Read(moduleData) + require.NoError(t, err) + + // Convert to upload format + upload, chunks := sdkproto.BytesToDataUpload(sdkproto.DataUploadType_UPLOAD_TYPE_MODULE_FILES, moduleData) + + stream := newMockUploadStream(upload, chunks...) + + // Execute upload + err = server.UploadFile(stream) + require.NoError(t, err) + + // Upload should be done + require.True(t, stream.isDone(), "stream should be done after upload") + + // Verify file was stored in database + hashString := fmt.Sprintf("%x", upload.DataHash) + file, err := db.GetFileByHashAndCreator(ctx, database.GetFileByHashAndCreatorParams{ + Hash: hashString, + CreatedBy: uuid.Nil, // Provisionerd creates with Nil UUID + }) + require.NoError(t, err) + require.Equal(t, hashString, file.Hash) + require.Equal(t, moduleData, file.Data) + require.Equal(t, "application/x-tar", file.Mimetype) + + // Try to upload it again, and it should still be successful + stream = newMockUploadStream(upload, chunks...) + err = server.UploadFile(stream) + require.NoError(t, err, "re-upload should succeed without error") + require.True(t, stream.isDone(), "stream should be done after re-upload") + }) + } +} + +// TestUploadFileErrorScenarios tests various error conditions in file upload +func TestUploadFileErrorScenarios(t *testing.T) { + t.Parallel() + + //nolint:dogsled + server, _, _, _ := setup(t, false, &overrides{ + externalAuthConfigs: []*externalauth.Config{{}}, + }) + + // Generate test data + moduleData := make([]byte, sdkproto.ChunkSize*2) + _, err := crand.Read(moduleData) + require.NoError(t, err) + + upload, chunks := sdkproto.BytesToDataUpload(sdkproto.DataUploadType_UPLOAD_TYPE_MODULE_FILES, moduleData) + + t.Run("chunk_before_upload", func(t *testing.T) { + t.Parallel() + + stream := newMockUploadStream(nil, chunks[0]) + + err := server.UploadFile(stream) + require.ErrorContains(t, err, "unexpected chunk piece while waiting for file upload") + require.True(t, stream.isDone(), "stream should be done after error") + }) + + t.Run("duplicate_upload", func(t *testing.T) { + t.Parallel() + + stream := &mockUploadStream{ + done: make(chan struct{}), + messages: make(chan *proto.UploadFileRequest, 2), + } + + up := &proto.UploadFileRequest{Type: &proto.UploadFileRequest_DataUpload{DataUpload: upload}} + + // Send it twice + stream.messages <- up + stream.messages <- up + + err := server.UploadFile(stream) + require.ErrorContains(t, err, "unexpected file upload while waiting for file completion") + require.True(t, stream.isDone(), "stream should be done after error") + }) + + t.Run("unsupported_upload_type", func(t *testing.T) { + t.Parallel() + + //nolint:govet // Ignore lock copy + cpy := *upload + cpy.UploadType = sdkproto.DataUploadType_UPLOAD_TYPE_UNKNOWN // Set to an unsupported type + stream := newMockUploadStream(&cpy, chunks...) + + err := server.UploadFile(stream) + require.ErrorContains(t, err, "unsupported file upload type") + require.True(t, stream.isDone(), "stream should be done after error") + }) +} + +type mockUploadStream struct { + done chan struct{} + messages chan *proto.UploadFileRequest +} + +func (m mockUploadStream) SendAndClose(empty *proto.Empty) error { + close(m.done) + return nil +} + +func (m mockUploadStream) Recv() (*proto.UploadFileRequest, error) { + msg, ok := <-m.messages + if !ok { + return nil, xerrors.New("no more messages to receive") + } + return msg, nil +} +func (*mockUploadStream) Context() context.Context { panic(errUnimplemented) } +func (*mockUploadStream) MsgSend(msg drpc.Message, enc drpc.Encoding) error { + panic(errUnimplemented) +} + +func (*mockUploadStream) MsgRecv(msg drpc.Message, enc drpc.Encoding) error { + panic(errUnimplemented) +} +func (*mockUploadStream) CloseSend() error { panic(errUnimplemented) } +func (*mockUploadStream) Close() error { panic(errUnimplemented) } +func (m *mockUploadStream) isDone() bool { + select { + case <-m.done: + return true + default: + return false + } +} + +func newMockUploadStream(up *sdkproto.DataUpload, chunks ...*sdkproto.ChunkPiece) *mockUploadStream { + stream := &mockUploadStream{ + done: make(chan struct{}), + messages: make(chan *proto.UploadFileRequest, 1+len(chunks)), + } + if up != nil { + stream.messages <- &proto.UploadFileRequest{Type: &proto.UploadFileRequest_DataUpload{DataUpload: up}} + } + + for _, chunk := range chunks { + stream.messages <- &proto.UploadFileRequest{Type: &proto.UploadFileRequest_ChunkPiece{ChunkPiece: chunk}} + } + close(stream.messages) + return stream +} diff --git a/provisioner/terraform/executor.go b/provisioner/terraform/executor.go index 6d3c6de5e902d..b29c21eff000c 100644 --- a/provisioner/terraform/executor.go +++ b/provisioner/terraform/executor.go @@ -19,13 +19,11 @@ import ( tfjson "github.com/hashicorp/terraform-json" "go.opentelemetry.io/otel/attribute" "golang.org/x/xerrors" - protobuf "google.golang.org/protobuf/proto" "cdr.dev/slog" "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/tracing" - "github.com/coder/coder/v2/codersdk/drpcsdk" "github.com/coder/coder/v2/provisionersdk/proto" ) @@ -260,13 +258,15 @@ func getStateFilePath(workdir string) string { } // revive:disable-next-line:flag-parameter -func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr logSink, metadata *proto.Metadata) (*proto.PlanComplete, error) { +func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr logSink, req *proto.PlanRequest) (*proto.PlanComplete, error) { ctx, span := e.server.startTrace(ctx, tracing.FuncName()) defer span.End() e.mut.Lock() defer e.mut.Unlock() + metadata := req.Metadata + planfilePath := getPlanFilePath(e.workdir) args := []string{ "plan", @@ -314,10 +314,16 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l graphTimings.ingest(createGraphTimingsEvent(timingGraphComplete)) - moduleFiles, err := GetModulesArchive(os.DirFS(e.workdir)) - if err != nil { - // TODO: we probably want to persist this error or make it louder eventually - e.logger.Warn(ctx, "failed to archive terraform modules", slog.Error(err)) + var moduleFiles []byte + // Skipping modules archiving is useful if the caller does not need it, eg during + // a workspace build. This removes some added costs of sending the modules + // payload back to coderd if coderd is just going to ignore it. + if !req.OmitModuleFiles { + moduleFiles, err = GetModulesArchive(os.DirFS(e.workdir)) + if err != nil { + // TODO: we probably want to persist this error or make it louder eventually + e.logger.Warn(ctx, "failed to archive terraform modules", slog.Error(err)) + } } // When a prebuild claim attempt is made, log a warning if a resource is due to be replaced, since this will obviate @@ -357,11 +363,6 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l ModuleFiles: moduleFiles, } - if protobuf.Size(msg) > drpcsdk.MaxMessageSize { - e.logger.Warn(ctx, "cannot persist terraform modules, message payload too big", slog.F("archive_size", len(msg.ModuleFiles))) - msg.ModuleFiles = nil - } - return msg, nil } diff --git a/provisioner/terraform/modules.go b/provisioner/terraform/modules.go index e0da5f1578069..f0b40ea9517e0 100644 --- a/provisioner/terraform/modules.go +++ b/provisioner/terraform/modules.go @@ -13,9 +13,21 @@ import ( "golang.org/x/xerrors" + "github.com/coder/coder/v2/coderd/util/xio" "github.com/coder/coder/v2/provisionersdk/proto" ) +const ( + // MaximumModuleArchiveSize limits the total size of a module archive. + // At some point, the user should take steps to reduce the size of their + // template modules, as this can lead to performance issues + // TODO: Determine what a reasonable limit is for modules + // If we start hitting this limit, we might want to consider adding + // configurable filters? Files like images could blow up the size of a + // module. + MaximumModuleArchiveSize = 20 * 1024 * 1024 // 20MB +) + type module struct { Source string `json:"Source"` Version string `json:"Version"` @@ -85,7 +97,9 @@ func GetModulesArchive(root fs.FS) ([]byte, error) { empty := true var b bytes.Buffer - w := tar.NewWriter(&b) + + lw := xio.NewLimitWriter(&b, MaximumModuleArchiveSize) + w := tar.NewWriter(lw) for _, it := range m.Modules { // Check to make sure that the module is a remote module fetched by diff --git a/provisioner/terraform/provision.go b/provisioner/terraform/provision.go index 84c630eec48fe..50648a4d3ef1e 100644 --- a/provisioner/terraform/provision.go +++ b/provisioner/terraform/provision.go @@ -163,7 +163,7 @@ func (s *server) Plan( return provisionersdk.PlanErrorf("plan vars: %s", err) } - resp, err := e.plan(ctx, killCtx, env, vars, sess, request.Metadata) + resp, err := e.plan(ctx, killCtx, env, vars, sess, request) if err != nil { return provisionersdk.PlanErrorf("%s", err.Error()) } diff --git a/provisionerd/proto/provisionerd.pb.go b/provisionerd/proto/provisionerd.pb.go index 41bc91591e017..b4343eafbfdac 100644 --- a/provisionerd/proto/provisionerd.pb.go +++ b/provisionerd/proto/provisionerd.pb.go @@ -855,6 +855,87 @@ func (*CancelAcquire) Descriptor() ([]byte, []int) { return file_provisionerd_proto_provisionerd_proto_rawDescGZIP(), []int{9} } +type UploadFileRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Type: + // + // *UploadFileRequest_DataUpload + // *UploadFileRequest_ChunkPiece + Type isUploadFileRequest_Type `protobuf_oneof:"type"` +} + +func (x *UploadFileRequest) Reset() { + *x = UploadFileRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UploadFileRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UploadFileRequest) ProtoMessage() {} + +func (x *UploadFileRequest) ProtoReflect() protoreflect.Message { + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UploadFileRequest.ProtoReflect.Descriptor instead. +func (*UploadFileRequest) Descriptor() ([]byte, []int) { + return file_provisionerd_proto_provisionerd_proto_rawDescGZIP(), []int{10} +} + +func (m *UploadFileRequest) GetType() isUploadFileRequest_Type { + if m != nil { + return m.Type + } + return nil +} + +func (x *UploadFileRequest) GetDataUpload() *proto.DataUpload { + if x, ok := x.GetType().(*UploadFileRequest_DataUpload); ok { + return x.DataUpload + } + return nil +} + +func (x *UploadFileRequest) GetChunkPiece() *proto.ChunkPiece { + if x, ok := x.GetType().(*UploadFileRequest_ChunkPiece); ok { + return x.ChunkPiece + } + return nil +} + +type isUploadFileRequest_Type interface { + isUploadFileRequest_Type() +} + +type UploadFileRequest_DataUpload struct { + DataUpload *proto.DataUpload `protobuf:"bytes,1,opt,name=data_upload,json=dataUpload,proto3,oneof"` +} + +type UploadFileRequest_ChunkPiece struct { + ChunkPiece *proto.ChunkPiece `protobuf:"bytes,2,opt,name=chunk_piece,json=chunkPiece,proto3,oneof"` +} + +func (*UploadFileRequest_DataUpload) isUploadFileRequest_Type() {} + +func (*UploadFileRequest_ChunkPiece) isUploadFileRequest_Type() {} + type AcquiredJob_WorkspaceBuild struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -877,7 +958,7 @@ type AcquiredJob_WorkspaceBuild struct { func (x *AcquiredJob_WorkspaceBuild) Reset() { *x = AcquiredJob_WorkspaceBuild{} if protoimpl.UnsafeEnabled { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[10] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -890,7 +971,7 @@ func (x *AcquiredJob_WorkspaceBuild) String() string { func (*AcquiredJob_WorkspaceBuild) ProtoMessage() {} func (x *AcquiredJob_WorkspaceBuild) ProtoReflect() protoreflect.Message { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[10] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -981,7 +1062,7 @@ type AcquiredJob_TemplateImport struct { func (x *AcquiredJob_TemplateImport) Reset() { *x = AcquiredJob_TemplateImport{} if protoimpl.UnsafeEnabled { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[11] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -994,7 +1075,7 @@ func (x *AcquiredJob_TemplateImport) String() string { func (*AcquiredJob_TemplateImport) ProtoMessage() {} func (x *AcquiredJob_TemplateImport) ProtoReflect() protoreflect.Message { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[11] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1037,7 +1118,7 @@ type AcquiredJob_TemplateDryRun struct { func (x *AcquiredJob_TemplateDryRun) Reset() { *x = AcquiredJob_TemplateDryRun{} if protoimpl.UnsafeEnabled { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[12] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1050,7 +1131,7 @@ func (x *AcquiredJob_TemplateDryRun) String() string { func (*AcquiredJob_TemplateDryRun) ProtoMessage() {} func (x *AcquiredJob_TemplateDryRun) ProtoReflect() protoreflect.Message { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[12] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1099,7 +1180,7 @@ type FailedJob_WorkspaceBuild struct { func (x *FailedJob_WorkspaceBuild) Reset() { *x = FailedJob_WorkspaceBuild{} if protoimpl.UnsafeEnabled { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[14] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1112,7 +1193,7 @@ func (x *FailedJob_WorkspaceBuild) String() string { func (*FailedJob_WorkspaceBuild) ProtoMessage() {} func (x *FailedJob_WorkspaceBuild) ProtoReflect() protoreflect.Message { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[14] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1151,7 +1232,7 @@ type FailedJob_TemplateImport struct { func (x *FailedJob_TemplateImport) Reset() { *x = FailedJob_TemplateImport{} if protoimpl.UnsafeEnabled { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[15] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1164,7 +1245,7 @@ func (x *FailedJob_TemplateImport) String() string { func (*FailedJob_TemplateImport) ProtoMessage() {} func (x *FailedJob_TemplateImport) ProtoReflect() protoreflect.Message { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[15] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1189,7 +1270,7 @@ type FailedJob_TemplateDryRun struct { func (x *FailedJob_TemplateDryRun) Reset() { *x = FailedJob_TemplateDryRun{} if protoimpl.UnsafeEnabled { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[16] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1202,7 +1283,7 @@ func (x *FailedJob_TemplateDryRun) String() string { func (*FailedJob_TemplateDryRun) ProtoMessage() {} func (x *FailedJob_TemplateDryRun) ProtoReflect() protoreflect.Message { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[16] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1233,7 +1314,7 @@ type CompletedJob_WorkspaceBuild struct { func (x *CompletedJob_WorkspaceBuild) Reset() { *x = CompletedJob_WorkspaceBuild{} if protoimpl.UnsafeEnabled { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[17] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1246,7 +1327,7 @@ func (x *CompletedJob_WorkspaceBuild) String() string { func (*CompletedJob_WorkspaceBuild) ProtoMessage() {} func (x *CompletedJob_WorkspaceBuild) ProtoReflect() protoreflect.Message { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[17] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1312,12 +1393,13 @@ type CompletedJob_TemplateImport struct { Presets []*proto.Preset `protobuf:"bytes,8,rep,name=presets,proto3" json:"presets,omitempty"` Plan []byte `protobuf:"bytes,9,opt,name=plan,proto3" json:"plan,omitempty"` ModuleFiles []byte `protobuf:"bytes,10,opt,name=module_files,json=moduleFiles,proto3" json:"module_files,omitempty"` + ModuleFilesHash []byte `protobuf:"bytes,11,opt,name=module_files_hash,json=moduleFilesHash,proto3" json:"module_files_hash,omitempty"` } func (x *CompletedJob_TemplateImport) Reset() { *x = CompletedJob_TemplateImport{} if protoimpl.UnsafeEnabled { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[18] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1330,7 +1412,7 @@ func (x *CompletedJob_TemplateImport) String() string { func (*CompletedJob_TemplateImport) ProtoMessage() {} func (x *CompletedJob_TemplateImport) ProtoReflect() protoreflect.Message { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[18] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1416,6 +1498,13 @@ func (x *CompletedJob_TemplateImport) GetModuleFiles() []byte { return nil } +func (x *CompletedJob_TemplateImport) GetModuleFilesHash() []byte { + if x != nil { + return x.ModuleFilesHash + } + return nil +} + type CompletedJob_TemplateDryRun struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1428,7 +1517,7 @@ type CompletedJob_TemplateDryRun struct { func (x *CompletedJob_TemplateDryRun) Reset() { *x = CompletedJob_TemplateDryRun{} if protoimpl.UnsafeEnabled { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[19] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1441,7 +1530,7 @@ func (x *CompletedJob_TemplateDryRun) String() string { func (*CompletedJob_TemplateDryRun) ProtoMessage() {} func (x *CompletedJob_TemplateDryRun) ProtoReflect() protoreflect.Message { - mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[19] + mi := &file_provisionerd_proto_provisionerd_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1605,7 +1694,7 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{ 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x10, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x1a, 0x10, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, - 0x6e, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x8d, 0x0a, 0x0a, 0x0c, 0x43, 0x6f, + 0x6e, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xb9, 0x0a, 0x0a, 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x54, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x62, @@ -1641,7 +1730,7 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{ 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x14, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x61, - 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0xd1, 0x04, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, + 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0xfd, 0x04, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x3e, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, @@ -1678,108 +1767,125 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{ 0x73, 0x65, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, - 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x1a, 0x74, 0x0a, 0x0e, 0x54, - 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x33, 0x0a, - 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, - 0x72, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, - 0x73, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xb0, 0x01, 0x0a, 0x03, 0x4c, 0x6f, - 0x67, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, - 0x2e, 0x4c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, - 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, - 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x14, - 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, - 0x74, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22, 0xa6, 0x03, 0x0a, - 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x12, - 0x4c, 0x0a, 0x12, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x72, 0x69, - 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x11, 0x74, 0x65, 0x6d, 0x70, - 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x4c, 0x0a, - 0x14, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, + 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, + 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x74, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x2d, + 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4d, 0x6f, + 0x64, 0x75, 0x6c, 0x65, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x42, 0x06, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xb0, 0x01, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x2f, 0x0a, + 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2b, + 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, + 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22, 0xa6, 0x03, 0x0a, 0x10, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, + 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, + 0x6f, 0x62, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x4c, 0x0a, 0x12, 0x74, + 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, + 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x11, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, + 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x4c, 0x0a, 0x14, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x12, 0x75, 0x73, 0x65, 0x72, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, + 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x12, + 0x58, 0x0a, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x61, 0x67, + 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 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, 0x4a, 0x04, 0x08, 0x03, 0x10, + 0x04, 0x22, 0x7a, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x65, 0x64, 0x12, 0x43, 0x0a, 0x0f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, - 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x75, 0x73, 0x65, 0x72, 0x56, 0x61, 0x72, - 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, - 0x65, 0x61, 0x64, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x65, 0x61, - 0x64, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x57, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, - 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x1a, 0x40, 0x0a, - 0x12, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 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, 0x4a, - 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0x7a, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, - 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x12, 0x43, 0x0a, 0x0f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, - 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x61, - 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x76, 0x61, 0x72, - 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, - 0x03, 0x22, 0x4a, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x1d, - 0x0a, 0x0a, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x09, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x68, 0x0a, - 0x13, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x02, 0x6f, 0x6b, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x5f, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, - 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x12, - 0x16, 0x0a, 0x06, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x06, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x22, 0x0f, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, - 0x6c, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x2a, 0x34, 0x0a, 0x09, 0x4c, 0x6f, 0x67, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, - 0x4f, 0x4e, 0x45, 0x52, 0x5f, 0x44, 0x41, 0x45, 0x4d, 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a, - 0x0b, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x45, 0x52, 0x10, 0x01, 0x32, 0xc5, - 0x03, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x44, 0x61, - 0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0a, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4a, - 0x6f, 0x62, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4a, - 0x6f, 0x62, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x52, 0x0a, 0x14, 0x41, 0x63, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x4a, 0x6f, 0x62, 0x57, 0x69, 0x74, 0x68, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x12, - 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, - 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x1a, 0x19, 0x2e, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x41, 0x63, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x01, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x0b, 0x43, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, + 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, + 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0x4a, 0x0a, + 0x12, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x61, + 0x69, 0x6c, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, + 0x64, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x68, 0x0a, 0x13, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, + 0x12, 0x29, 0x0a, 0x10, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6d, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x63, 0x72, 0x65, 0x64, + 0x69, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, + 0x75, 0x64, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x62, 0x75, 0x64, + 0x67, 0x65, 0x74, 0x22, 0x0f, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x63, 0x71, + 0x75, 0x69, 0x72, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, + 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0b, 0x64, 0x61, + 0x74, 0x61, 0x5f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x44, 0x61, + 0x74, 0x61, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, + 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x3a, 0x0a, 0x0b, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x5f, + 0x70, 0x69, 0x65, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x50, + 0x69, 0x65, 0x63, 0x65, 0x48, 0x00, 0x52, 0x0a, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x69, 0x65, + 0x63, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, 0x34, 0x0a, 0x09, 0x4c, 0x6f, + 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x52, 0x4f, 0x56, 0x49, + 0x53, 0x49, 0x4f, 0x4e, 0x45, 0x52, 0x5f, 0x44, 0x41, 0x45, 0x4d, 0x4f, 0x4e, 0x10, 0x00, 0x12, + 0x0f, 0x0a, 0x0b, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x45, 0x52, 0x10, 0x01, + 0x32, 0x8b, 0x04, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0a, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, + 0x64, 0x4a, 0x6f, 0x62, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x52, 0x0a, 0x14, 0x41, 0x63, 0x71, + 0x75, 0x69, 0x72, 0x65, 0x4a, 0x6f, 0x62, 0x57, 0x69, 0x74, 0x68, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, + 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x1a, 0x19, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x41, 0x63, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x01, 0x30, 0x01, 0x12, 0x52, 0x0a, + 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x4c, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x1e, 0x2e, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, - 0x07, 0x46, 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, - 0x62, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, - 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, - 0x62, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, - 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x4c, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x1e, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x37, 0x0a, 0x07, 0x46, 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, + 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, + 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x44, 0x0a, 0x0a, 0x55, 0x70, 0x6c, 0x6f, + 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x28, 0x01, 0x42, 0x2e, + 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, + 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1795,7 +1901,7 @@ func file_provisionerd_proto_provisionerd_proto_rawDescGZIP() []byte { } var file_provisionerd_proto_provisionerd_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_provisionerd_proto_provisionerd_proto_msgTypes = make([]protoimpl.MessageInfo, 21) +var file_provisionerd_proto_provisionerd_proto_msgTypes = make([]protoimpl.MessageInfo, 22) var file_provisionerd_proto_provisionerd_proto_goTypes = []interface{}{ (LogSource)(0), // 0: provisionerd.LogSource (*Empty)(nil), // 1: provisionerd.Empty @@ -1808,90 +1914,97 @@ var file_provisionerd_proto_provisionerd_proto_goTypes = []interface{}{ (*CommitQuotaRequest)(nil), // 8: provisionerd.CommitQuotaRequest (*CommitQuotaResponse)(nil), // 9: provisionerd.CommitQuotaResponse (*CancelAcquire)(nil), // 10: provisionerd.CancelAcquire - (*AcquiredJob_WorkspaceBuild)(nil), // 11: provisionerd.AcquiredJob.WorkspaceBuild - (*AcquiredJob_TemplateImport)(nil), // 12: provisionerd.AcquiredJob.TemplateImport - (*AcquiredJob_TemplateDryRun)(nil), // 13: provisionerd.AcquiredJob.TemplateDryRun - nil, // 14: provisionerd.AcquiredJob.TraceMetadataEntry - (*FailedJob_WorkspaceBuild)(nil), // 15: provisionerd.FailedJob.WorkspaceBuild - (*FailedJob_TemplateImport)(nil), // 16: provisionerd.FailedJob.TemplateImport - (*FailedJob_TemplateDryRun)(nil), // 17: provisionerd.FailedJob.TemplateDryRun - (*CompletedJob_WorkspaceBuild)(nil), // 18: provisionerd.CompletedJob.WorkspaceBuild - (*CompletedJob_TemplateImport)(nil), // 19: provisionerd.CompletedJob.TemplateImport - (*CompletedJob_TemplateDryRun)(nil), // 20: provisionerd.CompletedJob.TemplateDryRun - nil, // 21: provisionerd.UpdateJobRequest.WorkspaceTagsEntry - (proto.LogLevel)(0), // 22: provisioner.LogLevel - (*proto.TemplateVariable)(nil), // 23: provisioner.TemplateVariable - (*proto.VariableValue)(nil), // 24: provisioner.VariableValue - (*proto.RichParameterValue)(nil), // 25: provisioner.RichParameterValue - (*proto.ExternalAuthProvider)(nil), // 26: provisioner.ExternalAuthProvider - (*proto.Metadata)(nil), // 27: provisioner.Metadata - (*proto.Timing)(nil), // 28: provisioner.Timing - (*proto.Resource)(nil), // 29: provisioner.Resource - (*proto.Module)(nil), // 30: provisioner.Module - (*proto.ResourceReplacement)(nil), // 31: provisioner.ResourceReplacement - (*proto.RichParameter)(nil), // 32: provisioner.RichParameter - (*proto.ExternalAuthProviderResource)(nil), // 33: provisioner.ExternalAuthProviderResource - (*proto.Preset)(nil), // 34: provisioner.Preset + (*UploadFileRequest)(nil), // 11: provisionerd.UploadFileRequest + (*AcquiredJob_WorkspaceBuild)(nil), // 12: provisionerd.AcquiredJob.WorkspaceBuild + (*AcquiredJob_TemplateImport)(nil), // 13: provisionerd.AcquiredJob.TemplateImport + (*AcquiredJob_TemplateDryRun)(nil), // 14: provisionerd.AcquiredJob.TemplateDryRun + nil, // 15: provisionerd.AcquiredJob.TraceMetadataEntry + (*FailedJob_WorkspaceBuild)(nil), // 16: provisionerd.FailedJob.WorkspaceBuild + (*FailedJob_TemplateImport)(nil), // 17: provisionerd.FailedJob.TemplateImport + (*FailedJob_TemplateDryRun)(nil), // 18: provisionerd.FailedJob.TemplateDryRun + (*CompletedJob_WorkspaceBuild)(nil), // 19: provisionerd.CompletedJob.WorkspaceBuild + (*CompletedJob_TemplateImport)(nil), // 20: provisionerd.CompletedJob.TemplateImport + (*CompletedJob_TemplateDryRun)(nil), // 21: provisionerd.CompletedJob.TemplateDryRun + nil, // 22: provisionerd.UpdateJobRequest.WorkspaceTagsEntry + (proto.LogLevel)(0), // 23: provisioner.LogLevel + (*proto.TemplateVariable)(nil), // 24: provisioner.TemplateVariable + (*proto.VariableValue)(nil), // 25: provisioner.VariableValue + (*proto.DataUpload)(nil), // 26: provisioner.DataUpload + (*proto.ChunkPiece)(nil), // 27: provisioner.ChunkPiece + (*proto.RichParameterValue)(nil), // 28: provisioner.RichParameterValue + (*proto.ExternalAuthProvider)(nil), // 29: provisioner.ExternalAuthProvider + (*proto.Metadata)(nil), // 30: provisioner.Metadata + (*proto.Timing)(nil), // 31: provisioner.Timing + (*proto.Resource)(nil), // 32: provisioner.Resource + (*proto.Module)(nil), // 33: provisioner.Module + (*proto.ResourceReplacement)(nil), // 34: provisioner.ResourceReplacement + (*proto.RichParameter)(nil), // 35: provisioner.RichParameter + (*proto.ExternalAuthProviderResource)(nil), // 36: provisioner.ExternalAuthProviderResource + (*proto.Preset)(nil), // 37: provisioner.Preset } var file_provisionerd_proto_provisionerd_proto_depIdxs = []int32{ - 11, // 0: provisionerd.AcquiredJob.workspace_build:type_name -> provisionerd.AcquiredJob.WorkspaceBuild - 12, // 1: provisionerd.AcquiredJob.template_import:type_name -> provisionerd.AcquiredJob.TemplateImport - 13, // 2: provisionerd.AcquiredJob.template_dry_run:type_name -> provisionerd.AcquiredJob.TemplateDryRun - 14, // 3: provisionerd.AcquiredJob.trace_metadata:type_name -> provisionerd.AcquiredJob.TraceMetadataEntry - 15, // 4: provisionerd.FailedJob.workspace_build:type_name -> provisionerd.FailedJob.WorkspaceBuild - 16, // 5: provisionerd.FailedJob.template_import:type_name -> provisionerd.FailedJob.TemplateImport - 17, // 6: provisionerd.FailedJob.template_dry_run:type_name -> provisionerd.FailedJob.TemplateDryRun - 18, // 7: provisionerd.CompletedJob.workspace_build:type_name -> provisionerd.CompletedJob.WorkspaceBuild - 19, // 8: provisionerd.CompletedJob.template_import:type_name -> provisionerd.CompletedJob.TemplateImport - 20, // 9: provisionerd.CompletedJob.template_dry_run:type_name -> provisionerd.CompletedJob.TemplateDryRun + 12, // 0: provisionerd.AcquiredJob.workspace_build:type_name -> provisionerd.AcquiredJob.WorkspaceBuild + 13, // 1: provisionerd.AcquiredJob.template_import:type_name -> provisionerd.AcquiredJob.TemplateImport + 14, // 2: provisionerd.AcquiredJob.template_dry_run:type_name -> provisionerd.AcquiredJob.TemplateDryRun + 15, // 3: provisionerd.AcquiredJob.trace_metadata:type_name -> provisionerd.AcquiredJob.TraceMetadataEntry + 16, // 4: provisionerd.FailedJob.workspace_build:type_name -> provisionerd.FailedJob.WorkspaceBuild + 17, // 5: provisionerd.FailedJob.template_import:type_name -> provisionerd.FailedJob.TemplateImport + 18, // 6: provisionerd.FailedJob.template_dry_run:type_name -> provisionerd.FailedJob.TemplateDryRun + 19, // 7: provisionerd.CompletedJob.workspace_build:type_name -> provisionerd.CompletedJob.WorkspaceBuild + 20, // 8: provisionerd.CompletedJob.template_import:type_name -> provisionerd.CompletedJob.TemplateImport + 21, // 9: provisionerd.CompletedJob.template_dry_run:type_name -> provisionerd.CompletedJob.TemplateDryRun 0, // 10: provisionerd.Log.source:type_name -> provisionerd.LogSource - 22, // 11: provisionerd.Log.level:type_name -> provisioner.LogLevel + 23, // 11: provisionerd.Log.level:type_name -> provisioner.LogLevel 5, // 12: provisionerd.UpdateJobRequest.logs:type_name -> provisionerd.Log - 23, // 13: provisionerd.UpdateJobRequest.template_variables:type_name -> provisioner.TemplateVariable - 24, // 14: provisionerd.UpdateJobRequest.user_variable_values:type_name -> provisioner.VariableValue - 21, // 15: provisionerd.UpdateJobRequest.workspace_tags:type_name -> provisionerd.UpdateJobRequest.WorkspaceTagsEntry - 24, // 16: provisionerd.UpdateJobResponse.variable_values:type_name -> provisioner.VariableValue - 25, // 17: provisionerd.AcquiredJob.WorkspaceBuild.rich_parameter_values:type_name -> provisioner.RichParameterValue - 24, // 18: provisionerd.AcquiredJob.WorkspaceBuild.variable_values:type_name -> provisioner.VariableValue - 26, // 19: provisionerd.AcquiredJob.WorkspaceBuild.external_auth_providers:type_name -> provisioner.ExternalAuthProvider - 27, // 20: provisionerd.AcquiredJob.WorkspaceBuild.metadata:type_name -> provisioner.Metadata - 25, // 21: provisionerd.AcquiredJob.WorkspaceBuild.previous_parameter_values:type_name -> provisioner.RichParameterValue - 27, // 22: provisionerd.AcquiredJob.TemplateImport.metadata:type_name -> provisioner.Metadata - 24, // 23: provisionerd.AcquiredJob.TemplateImport.user_variable_values:type_name -> provisioner.VariableValue - 25, // 24: provisionerd.AcquiredJob.TemplateDryRun.rich_parameter_values:type_name -> provisioner.RichParameterValue - 24, // 25: provisionerd.AcquiredJob.TemplateDryRun.variable_values:type_name -> provisioner.VariableValue - 27, // 26: provisionerd.AcquiredJob.TemplateDryRun.metadata:type_name -> provisioner.Metadata - 28, // 27: provisionerd.FailedJob.WorkspaceBuild.timings:type_name -> provisioner.Timing - 29, // 28: provisionerd.CompletedJob.WorkspaceBuild.resources:type_name -> provisioner.Resource - 28, // 29: provisionerd.CompletedJob.WorkspaceBuild.timings:type_name -> provisioner.Timing - 30, // 30: provisionerd.CompletedJob.WorkspaceBuild.modules:type_name -> provisioner.Module - 31, // 31: provisionerd.CompletedJob.WorkspaceBuild.resource_replacements:type_name -> provisioner.ResourceReplacement - 29, // 32: provisionerd.CompletedJob.TemplateImport.start_resources:type_name -> provisioner.Resource - 29, // 33: provisionerd.CompletedJob.TemplateImport.stop_resources:type_name -> provisioner.Resource - 32, // 34: provisionerd.CompletedJob.TemplateImport.rich_parameters:type_name -> provisioner.RichParameter - 33, // 35: provisionerd.CompletedJob.TemplateImport.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource - 30, // 36: provisionerd.CompletedJob.TemplateImport.start_modules:type_name -> provisioner.Module - 30, // 37: provisionerd.CompletedJob.TemplateImport.stop_modules:type_name -> provisioner.Module - 34, // 38: provisionerd.CompletedJob.TemplateImport.presets:type_name -> provisioner.Preset - 29, // 39: provisionerd.CompletedJob.TemplateDryRun.resources:type_name -> provisioner.Resource - 30, // 40: provisionerd.CompletedJob.TemplateDryRun.modules:type_name -> provisioner.Module - 1, // 41: provisionerd.ProvisionerDaemon.AcquireJob:input_type -> provisionerd.Empty - 10, // 42: provisionerd.ProvisionerDaemon.AcquireJobWithCancel:input_type -> provisionerd.CancelAcquire - 8, // 43: provisionerd.ProvisionerDaemon.CommitQuota:input_type -> provisionerd.CommitQuotaRequest - 6, // 44: provisionerd.ProvisionerDaemon.UpdateJob:input_type -> provisionerd.UpdateJobRequest - 3, // 45: provisionerd.ProvisionerDaemon.FailJob:input_type -> provisionerd.FailedJob - 4, // 46: provisionerd.ProvisionerDaemon.CompleteJob:input_type -> provisionerd.CompletedJob - 2, // 47: provisionerd.ProvisionerDaemon.AcquireJob:output_type -> provisionerd.AcquiredJob - 2, // 48: provisionerd.ProvisionerDaemon.AcquireJobWithCancel:output_type -> provisionerd.AcquiredJob - 9, // 49: provisionerd.ProvisionerDaemon.CommitQuota:output_type -> provisionerd.CommitQuotaResponse - 7, // 50: provisionerd.ProvisionerDaemon.UpdateJob:output_type -> provisionerd.UpdateJobResponse - 1, // 51: provisionerd.ProvisionerDaemon.FailJob:output_type -> provisionerd.Empty - 1, // 52: provisionerd.ProvisionerDaemon.CompleteJob:output_type -> provisionerd.Empty - 47, // [47:53] is the sub-list for method output_type - 41, // [41:47] is the sub-list for method input_type - 41, // [41:41] is the sub-list for extension type_name - 41, // [41:41] is the sub-list for extension extendee - 0, // [0:41] is the sub-list for field type_name + 24, // 13: provisionerd.UpdateJobRequest.template_variables:type_name -> provisioner.TemplateVariable + 25, // 14: provisionerd.UpdateJobRequest.user_variable_values:type_name -> provisioner.VariableValue + 22, // 15: provisionerd.UpdateJobRequest.workspace_tags:type_name -> provisionerd.UpdateJobRequest.WorkspaceTagsEntry + 25, // 16: provisionerd.UpdateJobResponse.variable_values:type_name -> provisioner.VariableValue + 26, // 17: provisionerd.UploadFileRequest.data_upload:type_name -> provisioner.DataUpload + 27, // 18: provisionerd.UploadFileRequest.chunk_piece:type_name -> provisioner.ChunkPiece + 28, // 19: provisionerd.AcquiredJob.WorkspaceBuild.rich_parameter_values:type_name -> provisioner.RichParameterValue + 25, // 20: provisionerd.AcquiredJob.WorkspaceBuild.variable_values:type_name -> provisioner.VariableValue + 29, // 21: provisionerd.AcquiredJob.WorkspaceBuild.external_auth_providers:type_name -> provisioner.ExternalAuthProvider + 30, // 22: provisionerd.AcquiredJob.WorkspaceBuild.metadata:type_name -> provisioner.Metadata + 28, // 23: provisionerd.AcquiredJob.WorkspaceBuild.previous_parameter_values:type_name -> provisioner.RichParameterValue + 30, // 24: provisionerd.AcquiredJob.TemplateImport.metadata:type_name -> provisioner.Metadata + 25, // 25: provisionerd.AcquiredJob.TemplateImport.user_variable_values:type_name -> provisioner.VariableValue + 28, // 26: provisionerd.AcquiredJob.TemplateDryRun.rich_parameter_values:type_name -> provisioner.RichParameterValue + 25, // 27: provisionerd.AcquiredJob.TemplateDryRun.variable_values:type_name -> provisioner.VariableValue + 30, // 28: provisionerd.AcquiredJob.TemplateDryRun.metadata:type_name -> provisioner.Metadata + 31, // 29: provisionerd.FailedJob.WorkspaceBuild.timings:type_name -> provisioner.Timing + 32, // 30: provisionerd.CompletedJob.WorkspaceBuild.resources:type_name -> provisioner.Resource + 31, // 31: provisionerd.CompletedJob.WorkspaceBuild.timings:type_name -> provisioner.Timing + 33, // 32: provisionerd.CompletedJob.WorkspaceBuild.modules:type_name -> provisioner.Module + 34, // 33: provisionerd.CompletedJob.WorkspaceBuild.resource_replacements:type_name -> provisioner.ResourceReplacement + 32, // 34: provisionerd.CompletedJob.TemplateImport.start_resources:type_name -> provisioner.Resource + 32, // 35: provisionerd.CompletedJob.TemplateImport.stop_resources:type_name -> provisioner.Resource + 35, // 36: provisionerd.CompletedJob.TemplateImport.rich_parameters:type_name -> provisioner.RichParameter + 36, // 37: provisionerd.CompletedJob.TemplateImport.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource + 33, // 38: provisionerd.CompletedJob.TemplateImport.start_modules:type_name -> provisioner.Module + 33, // 39: provisionerd.CompletedJob.TemplateImport.stop_modules:type_name -> provisioner.Module + 37, // 40: provisionerd.CompletedJob.TemplateImport.presets:type_name -> provisioner.Preset + 32, // 41: provisionerd.CompletedJob.TemplateDryRun.resources:type_name -> provisioner.Resource + 33, // 42: provisionerd.CompletedJob.TemplateDryRun.modules:type_name -> provisioner.Module + 1, // 43: provisionerd.ProvisionerDaemon.AcquireJob:input_type -> provisionerd.Empty + 10, // 44: provisionerd.ProvisionerDaemon.AcquireJobWithCancel:input_type -> provisionerd.CancelAcquire + 8, // 45: provisionerd.ProvisionerDaemon.CommitQuota:input_type -> provisionerd.CommitQuotaRequest + 6, // 46: provisionerd.ProvisionerDaemon.UpdateJob:input_type -> provisionerd.UpdateJobRequest + 3, // 47: provisionerd.ProvisionerDaemon.FailJob:input_type -> provisionerd.FailedJob + 4, // 48: provisionerd.ProvisionerDaemon.CompleteJob:input_type -> provisionerd.CompletedJob + 11, // 49: provisionerd.ProvisionerDaemon.UploadFile:input_type -> provisionerd.UploadFileRequest + 2, // 50: provisionerd.ProvisionerDaemon.AcquireJob:output_type -> provisionerd.AcquiredJob + 2, // 51: provisionerd.ProvisionerDaemon.AcquireJobWithCancel:output_type -> provisionerd.AcquiredJob + 9, // 52: provisionerd.ProvisionerDaemon.CommitQuota:output_type -> provisionerd.CommitQuotaResponse + 7, // 53: provisionerd.ProvisionerDaemon.UpdateJob:output_type -> provisionerd.UpdateJobResponse + 1, // 54: provisionerd.ProvisionerDaemon.FailJob:output_type -> provisionerd.Empty + 1, // 55: provisionerd.ProvisionerDaemon.CompleteJob:output_type -> provisionerd.Empty + 1, // 56: provisionerd.ProvisionerDaemon.UploadFile:output_type -> provisionerd.Empty + 50, // [50:57] is the sub-list for method output_type + 43, // [43:50] is the sub-list for method input_type + 43, // [43:43] is the sub-list for extension type_name + 43, // [43:43] is the sub-list for extension extendee + 0, // [0:43] is the sub-list for field type_name } func init() { file_provisionerd_proto_provisionerd_proto_init() } @@ -2021,7 +2134,7 @@ func file_provisionerd_proto_provisionerd_proto_init() { } } file_provisionerd_proto_provisionerd_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AcquiredJob_WorkspaceBuild); i { + switch v := v.(*UploadFileRequest); i { case 0: return &v.state case 1: @@ -2033,7 +2146,7 @@ func file_provisionerd_proto_provisionerd_proto_init() { } } file_provisionerd_proto_provisionerd_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AcquiredJob_TemplateImport); i { + switch v := v.(*AcquiredJob_WorkspaceBuild); i { case 0: return &v.state case 1: @@ -2045,6 +2158,18 @@ func file_provisionerd_proto_provisionerd_proto_init() { } } file_provisionerd_proto_provisionerd_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AcquiredJob_TemplateImport); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_provisionerd_proto_provisionerd_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AcquiredJob_TemplateDryRun); i { case 0: return &v.state @@ -2056,7 +2181,7 @@ func file_provisionerd_proto_provisionerd_proto_init() { return nil } } - file_provisionerd_proto_provisionerd_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + file_provisionerd_proto_provisionerd_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FailedJob_WorkspaceBuild); i { case 0: return &v.state @@ -2068,7 +2193,7 @@ func file_provisionerd_proto_provisionerd_proto_init() { return nil } } - file_provisionerd_proto_provisionerd_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_provisionerd_proto_provisionerd_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FailedJob_TemplateImport); i { case 0: return &v.state @@ -2080,7 +2205,7 @@ func file_provisionerd_proto_provisionerd_proto_init() { return nil } } - file_provisionerd_proto_provisionerd_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + file_provisionerd_proto_provisionerd_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FailedJob_TemplateDryRun); i { case 0: return &v.state @@ -2092,7 +2217,7 @@ func file_provisionerd_proto_provisionerd_proto_init() { return nil } } - file_provisionerd_proto_provisionerd_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + file_provisionerd_proto_provisionerd_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CompletedJob_WorkspaceBuild); i { case 0: return &v.state @@ -2104,7 +2229,7 @@ func file_provisionerd_proto_provisionerd_proto_init() { return nil } } - file_provisionerd_proto_provisionerd_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + file_provisionerd_proto_provisionerd_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CompletedJob_TemplateImport); i { case 0: return &v.state @@ -2116,7 +2241,7 @@ func file_provisionerd_proto_provisionerd_proto_init() { return nil } } - file_provisionerd_proto_provisionerd_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + file_provisionerd_proto_provisionerd_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CompletedJob_TemplateDryRun); i { case 0: return &v.state @@ -2144,13 +2269,17 @@ func file_provisionerd_proto_provisionerd_proto_init() { (*CompletedJob_TemplateImport_)(nil), (*CompletedJob_TemplateDryRun_)(nil), } + file_provisionerd_proto_provisionerd_proto_msgTypes[10].OneofWrappers = []interface{}{ + (*UploadFileRequest_DataUpload)(nil), + (*UploadFileRequest_ChunkPiece)(nil), + } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_provisionerd_proto_provisionerd_proto_rawDesc, NumEnums: 1, - NumMessages: 21, + NumMessages: 22, NumExtensions: 0, NumServices: 1, }, diff --git a/provisionerd/proto/provisionerd.proto b/provisionerd/proto/provisionerd.proto index adab9653ab1ef..1b5ede6e13c71 100644 --- a/provisionerd/proto/provisionerd.proto +++ b/provisionerd/proto/provisionerd.proto @@ -92,6 +92,7 @@ message CompletedJob { repeated provisioner.Preset presets = 8; bytes plan = 9; bytes module_files = 10; + bytes module_files_hash = 11; } message TemplateDryRun { repeated provisioner.Resource resources = 1; @@ -153,6 +154,13 @@ message CommitQuotaResponse { message CancelAcquire {} +message UploadFileRequest { + oneof type { + provisioner.DataUpload data_upload = 1; + provisioner.ChunkPiece chunk_piece = 2; + } +} + service ProvisionerDaemon { // AcquireJob requests a job. Implementations should // hold a lock on the job until CompleteJob() is @@ -180,4 +188,8 @@ service ProvisionerDaemon { // CompleteJob indicates a job has been completed. rpc CompleteJob(CompletedJob) returns (Empty); + + // UploadFile streams files to be inserted into the database. + // The file upload_type should be used to determine how to handle the file. + rpc UploadFile(stream UploadFileRequest) returns (Empty); } diff --git a/provisionerd/proto/provisionerd_drpc.pb.go b/provisionerd/proto/provisionerd_drpc.pb.go index 332624a435f6c..72f131b5c5fd6 100644 --- a/provisionerd/proto/provisionerd_drpc.pb.go +++ b/provisionerd/proto/provisionerd_drpc.pb.go @@ -44,6 +44,7 @@ type DRPCProvisionerDaemonClient interface { UpdateJob(ctx context.Context, in *UpdateJobRequest) (*UpdateJobResponse, error) FailJob(ctx context.Context, in *FailedJob) (*Empty, error) CompleteJob(ctx context.Context, in *CompletedJob) (*Empty, error) + UploadFile(ctx context.Context) (DRPCProvisionerDaemon_UploadFileClient, error) } type drpcProvisionerDaemonClient struct { @@ -140,6 +141,51 @@ func (c *drpcProvisionerDaemonClient) CompleteJob(ctx context.Context, in *Compl return out, nil } +func (c *drpcProvisionerDaemonClient) UploadFile(ctx context.Context) (DRPCProvisionerDaemon_UploadFileClient, error) { + stream, err := c.cc.NewStream(ctx, "/provisionerd.ProvisionerDaemon/UploadFile", drpcEncoding_File_provisionerd_proto_provisionerd_proto{}) + if err != nil { + return nil, err + } + x := &drpcProvisionerDaemon_UploadFileClient{stream} + return x, nil +} + +type DRPCProvisionerDaemon_UploadFileClient interface { + drpc.Stream + Send(*UploadFileRequest) error + CloseAndRecv() (*Empty, error) +} + +type drpcProvisionerDaemon_UploadFileClient struct { + drpc.Stream +} + +func (x *drpcProvisionerDaemon_UploadFileClient) GetStream() drpc.Stream { + return x.Stream +} + +func (x *drpcProvisionerDaemon_UploadFileClient) Send(m *UploadFileRequest) error { + return x.MsgSend(m, drpcEncoding_File_provisionerd_proto_provisionerd_proto{}) +} + +func (x *drpcProvisionerDaemon_UploadFileClient) CloseAndRecv() (*Empty, error) { + if err := x.CloseSend(); err != nil { + return nil, err + } + m := new(Empty) + if err := x.MsgRecv(m, drpcEncoding_File_provisionerd_proto_provisionerd_proto{}); err != nil { + return nil, err + } + return m, nil +} + +func (x *drpcProvisionerDaemon_UploadFileClient) CloseAndRecvMsg(m *Empty) error { + if err := x.CloseSend(); err != nil { + return err + } + return x.MsgRecv(m, drpcEncoding_File_provisionerd_proto_provisionerd_proto{}) +} + type DRPCProvisionerDaemonServer interface { AcquireJob(context.Context, *Empty) (*AcquiredJob, error) AcquireJobWithCancel(DRPCProvisionerDaemon_AcquireJobWithCancelStream) error @@ -147,6 +193,7 @@ type DRPCProvisionerDaemonServer interface { UpdateJob(context.Context, *UpdateJobRequest) (*UpdateJobResponse, error) FailJob(context.Context, *FailedJob) (*Empty, error) CompleteJob(context.Context, *CompletedJob) (*Empty, error) + UploadFile(DRPCProvisionerDaemon_UploadFileStream) error } type DRPCProvisionerDaemonUnimplementedServer struct{} @@ -175,9 +222,13 @@ func (s *DRPCProvisionerDaemonUnimplementedServer) CompleteJob(context.Context, return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented) } +func (s *DRPCProvisionerDaemonUnimplementedServer) UploadFile(DRPCProvisionerDaemon_UploadFileStream) error { + return drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented) +} + type DRPCProvisionerDaemonDescription struct{} -func (DRPCProvisionerDaemonDescription) NumMethods() int { return 6 } +func (DRPCProvisionerDaemonDescription) NumMethods() int { return 7 } func (DRPCProvisionerDaemonDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) { switch n { @@ -234,6 +285,14 @@ func (DRPCProvisionerDaemonDescription) Method(n int) (string, drpc.Encoding, dr in1.(*CompletedJob), ) }, DRPCProvisionerDaemonServer.CompleteJob, true + case 6: + return "/provisionerd.ProvisionerDaemon/UploadFile", drpcEncoding_File_provisionerd_proto_provisionerd_proto{}, + func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) { + return nil, srv.(DRPCProvisionerDaemonServer). + UploadFile( + &drpcProvisionerDaemon_UploadFileStream{in1.(drpc.Stream)}, + ) + }, DRPCProvisionerDaemonServer.UploadFile, true default: return "", nil, nil, nil, false } @@ -348,3 +407,32 @@ func (x *drpcProvisionerDaemon_CompleteJobStream) SendAndClose(m *Empty) error { } return x.CloseSend() } + +type DRPCProvisionerDaemon_UploadFileStream interface { + drpc.Stream + SendAndClose(*Empty) error + Recv() (*UploadFileRequest, error) +} + +type drpcProvisionerDaemon_UploadFileStream struct { + drpc.Stream +} + +func (x *drpcProvisionerDaemon_UploadFileStream) SendAndClose(m *Empty) error { + if err := x.MsgSend(m, drpcEncoding_File_provisionerd_proto_provisionerd_proto{}); err != nil { + return err + } + return x.CloseSend() +} + +func (x *drpcProvisionerDaemon_UploadFileStream) Recv() (*UploadFileRequest, error) { + m := new(UploadFileRequest) + if err := x.MsgRecv(m, drpcEncoding_File_provisionerd_proto_provisionerd_proto{}); err != nil { + return nil, err + } + return m, nil +} + +func (x *drpcProvisionerDaemon_UploadFileStream) RecvMsg(m *UploadFileRequest) error { + return x.MsgRecv(m, drpcEncoding_File_provisionerd_proto_provisionerd_proto{}) +} diff --git a/provisionerd/proto/version.go b/provisionerd/proto/version.go index 86a6e289c9329..0ba51936a917f 100644 --- a/provisionerd/proto/version.go +++ b/provisionerd/proto/version.go @@ -29,9 +29,14 @@ import "github.com/coder/coder/v2/apiversion" // `ttl` to define TTL-based expiration for unclaimed prebuilds. // - Add `group` field to `App` // - Add `form_type` field to parameters +// +// API v1.7: +// - Added DataUpload and ChunkPiece messages to support uploading large files +// back to Coderd. Used for uploading module files in support of dynamic +// parameters. const ( CurrentMajor = 1 - CurrentMinor = 6 + CurrentMinor = 7 ) // CurrentVersion is the current provisionerd API version. diff --git a/provisionerd/provisionerd.go b/provisionerd/provisionerd.go index 76a06d7fa68b1..707c69cde821c 100644 --- a/provisionerd/provisionerd.go +++ b/provisionerd/provisionerd.go @@ -2,6 +2,7 @@ package provisionerd import ( "context" + "crypto/sha256" "errors" "fmt" "io" @@ -18,8 +19,10 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.14.0" "go.opentelemetry.io/otel/trace" "golang.org/x/xerrors" + protobuf "google.golang.org/protobuf/proto" "cdr.dev/slog" + "github.com/coder/coder/v2/codersdk/drpcsdk" "github.com/coder/retry" "github.com/coder/coder/v2/coderd/tracing" @@ -515,7 +518,75 @@ func (p *Server) FailJob(ctx context.Context, in *proto.FailedJob) error { return err } +// UploadModuleFiles will insert a file into the database of coderd. +func (p *Server) UploadModuleFiles(ctx context.Context, moduleFiles []byte) error { + // Send the files separately if the message size is too large. + _, err := clientDoWithRetries(ctx, p.client, func(ctx context.Context, client proto.DRPCProvisionerDaemonClient) (*proto.Empty, error) { + // Add some timeout to prevent the stream from hanging indefinitely. + ctx, cancel := context.WithTimeout(ctx, 5*time.Minute) + defer cancel() + + stream, err := client.UploadFile(ctx) + if err != nil { + return nil, xerrors.Errorf("failed to start CompleteJobWithFiles stream: %w", err) + } + defer stream.Close() + + dataUp, chunks := sdkproto.BytesToDataUpload(sdkproto.DataUploadType_UPLOAD_TYPE_MODULE_FILES, moduleFiles) + + err = stream.Send(&proto.UploadFileRequest{Type: &proto.UploadFileRequest_DataUpload{DataUpload: dataUp}}) + if err != nil { + if retryable(err) { // Do not retry + return nil, xerrors.Errorf("send data upload: %s", err.Error()) + } + return nil, xerrors.Errorf("send data upload: %w", err) + } + + for i, chunk := range chunks { + err = stream.Send(&proto.UploadFileRequest{Type: &proto.UploadFileRequest_ChunkPiece{ChunkPiece: chunk}}) + if err != nil { + if retryable(err) { // Do not retry + return nil, xerrors.Errorf("send chunk piece: %s", err.Error()) + } + return nil, xerrors.Errorf("send chunk piece %d: %w", i, err) + } + } + + resp, err := stream.CloseAndRecv() + if err != nil { + if retryable(err) { // Do not retry + return nil, xerrors.Errorf("close stream: %s", err.Error()) + } + return nil, xerrors.Errorf("close stream: %w", err) + } + return resp, nil + }) + if err != nil { + return xerrors.Errorf("upload module files: %w", err) + } + + return nil +} + func (p *Server) CompleteJob(ctx context.Context, in *proto.CompletedJob) error { + // If the moduleFiles exceed the max message size, we need to upload them separately. + if ti, ok := in.Type.(*proto.CompletedJob_TemplateImport_); ok { + messageSize := protobuf.Size(in) + if messageSize > drpcsdk.MaxMessageSize && + messageSize-len(ti.TemplateImport.ModuleFiles) < drpcsdk.MaxMessageSize { + // Hashing the module files to reference them in the CompletedJob message. + moduleFilesHash := sha256.Sum256(ti.TemplateImport.ModuleFiles) + + moduleFiles := ti.TemplateImport.ModuleFiles + ti.TemplateImport.ModuleFiles = []byte{} // Clear the files in the final message + ti.TemplateImport.ModuleFilesHash = moduleFilesHash[:] + err := p.UploadModuleFiles(ctx, moduleFiles) + if err != nil { + return err + } + } + } + _, err := clientDoWithRetries(ctx, p.client, func(ctx context.Context, client proto.DRPCProvisionerDaemonClient) (*proto.Empty, error) { return client.CompleteJob(ctx, in) }) diff --git a/provisionerd/provisionerd_test.go b/provisionerd/provisionerd_test.go index 7a5d714befa05..1b4b6720b48e9 100644 --- a/provisionerd/provisionerd_test.go +++ b/provisionerd/provisionerd_test.go @@ -1269,6 +1269,10 @@ func (p *provisionerTestServer) Apply(s *provisionersdk.Session, r *sdkproto.App return p.apply(s, r, canceledOrComplete) } +func (p *provisionerDaemonTestServer) UploadFile(stream proto.DRPCProvisionerDaemon_UploadFileStream) error { + return p.uploadFile(stream) +} + // Fulfills the protobuf interface for a ProvisionerDaemon with // passable functions for dynamic functionality. type provisionerDaemonTestServer struct { @@ -1277,6 +1281,7 @@ type provisionerDaemonTestServer struct { updateJob func(ctx context.Context, update *proto.UpdateJobRequest) (*proto.UpdateJobResponse, error) failJob func(ctx context.Context, job *proto.FailedJob) (*proto.Empty, error) completeJob func(ctx context.Context, job *proto.CompletedJob) (*proto.Empty, error) + uploadFile func(stream proto.DRPCProvisionerDaemon_UploadFileStream) error } func (*provisionerDaemonTestServer) AcquireJob(context.Context, *proto.Empty) (*proto.AcquiredJob, error) { diff --git a/provisionerd/runner/runner.go b/provisionerd/runner/runner.go index 2894dadb8ff0a..305bd2543dd82 100644 --- a/provisionerd/runner/runner.go +++ b/provisionerd/runner/runner.go @@ -1,6 +1,7 @@ package runner import ( + "bytes" "context" "encoding/json" "errors" @@ -555,7 +556,7 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p CoderUrl: r.job.GetTemplateImport().Metadata.CoderUrl, WorkspaceOwnerGroups: r.job.GetTemplateImport().Metadata.WorkspaceOwnerGroups, WorkspaceTransition: sdkproto.WorkspaceTransition_START, - }) + }, false) if err != nil { return nil, r.failedJobf("template import provision for start: %s", err) } @@ -571,7 +572,8 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p CoderUrl: r.job.GetTemplateImport().Metadata.CoderUrl, WorkspaceOwnerGroups: r.job.GetTemplateImport().Metadata.WorkspaceOwnerGroups, WorkspaceTransition: sdkproto.WorkspaceTransition_STOP, - }) + }, true, // Modules downloaded on the start provision + ) if err != nil { return nil, r.failedJobf("template import provision for stop: %s", err) } @@ -597,7 +599,10 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p StopModules: stopProvision.Modules, Presets: startProvision.Presets, Plan: startProvision.Plan, - ModuleFiles: startProvision.ModuleFiles, + // ModuleFiles are not on the stopProvision. So grab from the startProvision. + ModuleFiles: startProvision.ModuleFiles, + // ModuleFileHash will be populated if the file is uploaded async + ModuleFilesHash: []byte{}, }, }, }, nil @@ -666,8 +671,8 @@ type templateImportProvision struct { // Performs a dry-run provision when importing a template. // This is used to detect resources that would be provisioned for a workspace in various states. // It doesn't define values for rich parameters as they're unknown during template import. -func (r *Runner) runTemplateImportProvision(ctx context.Context, variableValues []*sdkproto.VariableValue, metadata *sdkproto.Metadata) (*templateImportProvision, error) { - return r.runTemplateImportProvisionWithRichParameters(ctx, variableValues, nil, metadata) +func (r *Runner) runTemplateImportProvision(ctx context.Context, variableValues []*sdkproto.VariableValue, metadata *sdkproto.Metadata, omitModules bool) (*templateImportProvision, error) { + return r.runTemplateImportProvisionWithRichParameters(ctx, variableValues, nil, metadata, omitModules) } // Performs a dry-run provision with provided rich parameters. @@ -677,6 +682,7 @@ func (r *Runner) runTemplateImportProvisionWithRichParameters( variableValues []*sdkproto.VariableValue, richParameterValues []*sdkproto.RichParameterValue, metadata *sdkproto.Metadata, + omitModules bool, ) (*templateImportProvision, error) { ctx, span := r.startTrace(ctx, tracing.FuncName()) defer span.End() @@ -696,6 +702,7 @@ func (r *Runner) runTemplateImportProvisionWithRichParameters( // Template import has no previous values PreviousParameterValues: make([]*sdkproto.RichParameterValue, 0), VariableValues: variableValues, + OmitModuleFiles: omitModules, }}}) if err != nil { return nil, xerrors.Errorf("start provision: %w", err) @@ -717,11 +724,13 @@ func (r *Runner) runTemplateImportProvisionWithRichParameters( } }() + var moduleFilesUpload *sdkproto.DataBuilder for { msg, err := r.session.Recv() if err != nil { return nil, xerrors.Errorf("recv import provision: %w", err) } + switch msgType := msg.Type.(type) { case *sdkproto.Response_Log: r.logProvisionerJobLog(context.Background(), msgType.Log.Level, "template import provision job logged", @@ -735,6 +744,30 @@ func (r *Runner) runTemplateImportProvisionWithRichParameters( Output: msgType.Log.Output, Stage: stage, }) + case *sdkproto.Response_DataUpload: + c := msgType.DataUpload + if c.UploadType != sdkproto.DataUploadType_UPLOAD_TYPE_MODULE_FILES { + return nil, xerrors.Errorf("invalid data upload type: %q", c.UploadType) + } + + if moduleFilesUpload != nil { + return nil, xerrors.New("multiple module data uploads received, only expect 1") + } + + moduleFilesUpload, err = sdkproto.NewDataBuilder(c) + if err != nil { + return nil, xerrors.Errorf("create data builder: %w", err) + } + case *sdkproto.Response_ChunkPiece: + c := msgType.ChunkPiece + if moduleFilesUpload == nil { + return nil, xerrors.New("received chunk piece before module files data upload") + } + + _, err := moduleFilesUpload.Add(c) + if err != nil { + return nil, xerrors.Errorf("module files, add chunk piece: %w", err) + } case *sdkproto.Response_Plan: c := msgType.Plan if c.Error != "" { @@ -745,11 +778,27 @@ func (r *Runner) runTemplateImportProvisionWithRichParameters( return nil, xerrors.New(c.Error) } + if moduleFilesUpload != nil && len(c.ModuleFiles) > 0 { + return nil, xerrors.New("module files were uploaded and module files were returned in the plan response. Only one of these should be set") + } + r.logger.Info(context.Background(), "parse dry-run provision successful", slog.F("resource_count", len(c.Resources)), slog.F("resources", resourceNames(c.Resources)), ) + moduleFilesData := c.ModuleFiles + if moduleFilesUpload != nil { + uploadData, err := moduleFilesUpload.Complete() + if err != nil { + return nil, xerrors.Errorf("module files, complete upload: %w", err) + } + moduleFilesData = uploadData + if !bytes.Equal(c.ModuleFilesHash, moduleFilesUpload.Hash) { + return nil, xerrors.Errorf("module files hash mismatch, uploaded: %x, expected: %x", moduleFilesUpload.Hash, c.ModuleFilesHash) + } + } + return &templateImportProvision{ Resources: c.Resources, Parameters: c.Parameters, @@ -757,7 +806,7 @@ func (r *Runner) runTemplateImportProvisionWithRichParameters( Modules: c.Modules, Presets: c.Presets, Plan: c.Plan, - ModuleFiles: c.ModuleFiles, + ModuleFiles: moduleFilesData, }, nil default: return nil, xerrors.Errorf("invalid message type %q received from provisioner", @@ -810,6 +859,7 @@ func (r *Runner) runTemplateDryRun(ctx context.Context) (*proto.CompletedJob, *p r.job.GetTemplateDryRun().GetVariableValues(), r.job.GetTemplateDryRun().GetRichParameterValues(), metadata, + false, ) if err != nil { return nil, r.failedJobf("run dry-run provision job: %s", err) @@ -872,6 +922,10 @@ func (r *Runner) buildWorkspace(ctx context.Context, stage string, req *sdkproto Output: msgType.Log.Output, Stage: stage, }) + case *sdkproto.Response_DataUpload: + continue // Only for template imports + case *sdkproto.Response_ChunkPiece: + continue // Only for template imports default: // Stop looping! return msg, nil @@ -964,6 +1018,7 @@ func (r *Runner) runWorkspaceBuild(ctx context.Context) (*proto.CompletedJob, *p resp, failed := r.buildWorkspace(ctx, "Planning infrastructure", &sdkproto.Request{ Type: &sdkproto.Request_Plan{ Plan: &sdkproto.PlanRequest{ + OmitModuleFiles: true, // Only useful for template imports Metadata: r.job.GetWorkspaceBuild().Metadata, RichParameterValues: r.job.GetWorkspaceBuild().RichParameterValues, PreviousParameterValues: r.job.GetWorkspaceBuild().PreviousParameterValues, diff --git a/provisionersdk/proto/dataupload.go b/provisionersdk/proto/dataupload.go new file mode 100644 index 0000000000000..e9b6d9ddfb047 --- /dev/null +++ b/provisionersdk/proto/dataupload.go @@ -0,0 +1,139 @@ +package proto + +import ( + "bytes" + "crypto/sha256" + "sync" + + "golang.org/x/xerrors" +) + +const ( + ChunkSize = 2 << 20 // 2 MiB +) + +type DataBuilder struct { + Type DataUploadType + Hash []byte + Size int64 + ChunkCount int32 + + // chunkIndex is the index of the next chunk to be added. + chunkIndex int32 + mu sync.Mutex + data []byte +} + +func NewDataBuilder(req *DataUpload) (*DataBuilder, error) { + if len(req.DataHash) != 32 { + return nil, xerrors.Errorf("data hash must be 32 bytes, got %d bytes", len(req.DataHash)) + } + + return &DataBuilder{ + Type: req.UploadType, + Hash: req.DataHash, + Size: req.FileSize, + ChunkCount: req.Chunks, + + // Initial conditions + chunkIndex: 0, + data: make([]byte, 0, req.FileSize), + }, nil +} + +func (b *DataBuilder) Add(chunk *ChunkPiece) (bool, error) { + b.mu.Lock() + defer b.mu.Unlock() + + if !bytes.Equal(b.Hash, chunk.FullDataHash) { + return b.done(), xerrors.Errorf("data hash does not match, this chunk is for a different data upload") + } + + if b.done() { + return b.done(), xerrors.Errorf("data upload is already complete, cannot add more chunks") + } + + if chunk.PieceIndex != b.chunkIndex { + return b.done(), xerrors.Errorf("chunks ordering, expected chunk index %d, got %d", b.chunkIndex, chunk.PieceIndex) + } + + expectedSize := len(b.data) + len(chunk.Data) + if expectedSize > int(b.Size) { + return b.done(), xerrors.Errorf("data exceeds expected size, data is now %d bytes, %d bytes over the limit of %d", + expectedSize, b.Size-int64(expectedSize), b.Size) + } + + b.data = append(b.data, chunk.Data...) + b.chunkIndex++ + + return b.done(), nil +} + +// IsDone is always safe to call +func (b *DataBuilder) IsDone() bool { + b.mu.Lock() + defer b.mu.Unlock() + return b.done() +} + +func (b *DataBuilder) Complete() ([]byte, error) { + b.mu.Lock() + defer b.mu.Unlock() + + if !b.done() { + return nil, xerrors.Errorf("data upload is not complete, expected %d chunks, got %d", b.ChunkCount, b.chunkIndex) + } + + if len(b.data) != int(b.Size) { + return nil, xerrors.Errorf("data size mismatch, expected %d bytes, got %d bytes", b.Size, len(b.data)) + } + + hash := sha256.Sum256(b.data) + if !bytes.Equal(hash[:], b.Hash) { + return nil, xerrors.Errorf("data hash mismatch, expected %x, got %x", b.Hash, hash[:]) + } + + // A safe method would be to return a copy of the data, but that would have to + // allocate double the memory. Just return the original slice, and let the caller + // handle the memory management. + return b.data, nil +} + +func (b *DataBuilder) done() bool { + return b.chunkIndex >= b.ChunkCount +} + +func BytesToDataUpload(dataType DataUploadType, data []byte) (*DataUpload, []*ChunkPiece) { + fullHash := sha256.Sum256(data) + //nolint:gosec // not going over int32 + size := int32(len(data)) + // basically ceiling division to get the number of chunks required to + // hold the data, each chunk is ChunkSize bytes. + chunkCount := (size + ChunkSize - 1) / ChunkSize + + req := &DataUpload{ + DataHash: fullHash[:], + FileSize: int64(size), + Chunks: chunkCount, + UploadType: dataType, + } + + chunks := make([]*ChunkPiece, 0, chunkCount) + for i := int32(0); i < chunkCount; i++ { + start := int64(i) * ChunkSize + end := start + ChunkSize + if end > int64(size) { + end = int64(size) + } + chunkData := data[start:end] + + chunk := &ChunkPiece{ + PieceIndex: i, + Data: chunkData, + FullDataHash: fullHash[:], + } + chunks = append(chunks, chunk) + } + + return req, chunks +} diff --git a/provisionersdk/proto/dataupload_test.go b/provisionersdk/proto/dataupload_test.go new file mode 100644 index 0000000000000..496a7956c9cc6 --- /dev/null +++ b/provisionersdk/proto/dataupload_test.go @@ -0,0 +1,98 @@ +package proto_test + +import ( + crand "crypto/rand" + "math/rand" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/coder/coder/v2/provisionersdk/proto" +) + +// Fuzz must be run manually with the `-fuzz` flag to generate random test cases. +// By default, it only runs the added seed corpus cases. +// go test -fuzz=FuzzBytesToDataUpload +func FuzzBytesToDataUpload(f *testing.F) { + // Cases to always run in standard `go test` runs. + always := [][]byte{ + {}, + []byte("1"), + []byte("small"), + } + for _, data := range always { + f.Add(data) + } + + f.Fuzz(func(t *testing.T, data []byte) { + first, chunks := proto.BytesToDataUpload(proto.DataUploadType_UPLOAD_TYPE_MODULE_FILES, data) + + builder, err := proto.NewDataBuilder(first) + require.NoError(t, err) + + var done bool + for _, chunk := range chunks { + require.False(t, done) + done, err = builder.Add(chunk) + require.NoError(t, err) + } + + if len(chunks) > 0 { + require.True(t, done) + } + + finalData, err := builder.Complete() + require.NoError(t, err) + require.Equal(t, data, finalData) + }) +} + +// TestBytesToDataUpload tests the BytesToDataUpload function and the DataBuilder +// with large random data uploads. +func TestBytesToDataUpload(t *testing.T) { + t.Parallel() + + for i := 0; i < 20; i++ { + // Generate random data + //nolint:gosec // Just a unit test + chunkCount := 1 + rand.Intn(3) + //nolint:gosec // Just a unit test + size := (chunkCount * proto.ChunkSize) + (rand.Int() % proto.ChunkSize) + data := make([]byte, size) + _, err := crand.Read(data) + require.NoError(t, err) + + first, chunks := proto.BytesToDataUpload(proto.DataUploadType_UPLOAD_TYPE_MODULE_FILES, data) + builder, err := proto.NewDataBuilder(first) + require.NoError(t, err) + + // Try to add some bad chunks + _, err = builder.Add(&proto.ChunkPiece{Data: []byte{}, FullDataHash: make([]byte, 32)}) + require.ErrorContains(t, err, "data hash does not match") + + // Verify 'Complete' fails before adding any chunks + _, err = builder.Complete() + require.ErrorContains(t, err, "data upload is not complete") + + // Add the chunks + var done bool + for _, chunk := range chunks { + require.False(t, done, "data upload should not be complete before adding all chunks") + + done, err = builder.Add(chunk) + require.NoError(t, err, "chunk %d should be added successfully", chunk.PieceIndex) + } + require.True(t, done, "data upload should be complete after adding all chunks") + + // Try to add another chunk after completion + done, err = builder.Add(chunks[0]) + require.ErrorContains(t, err, "data upload is already complete") + require.True(t, done, "still complete") + + // Verify the final data matches the original + got, err := builder.Complete() + require.NoError(t, err) + + require.Equal(t, data, got, "final data should match the original data") + } +} diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go index 51d6bee4047b5..27739b700f6e0 100644 --- a/provisionersdk/proto/provisioner.pb.go +++ b/provisionersdk/proto/provisioner.pb.go @@ -397,6 +397,55 @@ func (TimingState) EnumDescriptor() ([]byte, []int) { return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{6} } +type DataUploadType int32 + +const ( + DataUploadType_UPLOAD_TYPE_UNKNOWN DataUploadType = 0 + // UPLOAD_TYPE_MODULE_FILES is used to stream over terraform module files. + // These files are located in `.terraform/modules` and are used for dynamic + // parameters. + DataUploadType_UPLOAD_TYPE_MODULE_FILES DataUploadType = 1 +) + +// Enum value maps for DataUploadType. +var ( + DataUploadType_name = map[int32]string{ + 0: "UPLOAD_TYPE_UNKNOWN", + 1: "UPLOAD_TYPE_MODULE_FILES", + } + DataUploadType_value = map[string]int32{ + "UPLOAD_TYPE_UNKNOWN": 0, + "UPLOAD_TYPE_MODULE_FILES": 1, + } +) + +func (x DataUploadType) Enum() *DataUploadType { + p := new(DataUploadType) + *p = x + return p +} + +func (x DataUploadType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DataUploadType) Descriptor() protoreflect.EnumDescriptor { + return file_provisionersdk_proto_provisioner_proto_enumTypes[7].Descriptor() +} + +func (DataUploadType) Type() protoreflect.EnumType { + return &file_provisionersdk_proto_provisioner_proto_enumTypes[7] +} + +func (x DataUploadType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DataUploadType.Descriptor instead. +func (DataUploadType) EnumDescriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{7} +} + // Empty indicates a successful request/response. type Empty struct { state protoimpl.MessageState @@ -2996,6 +3045,12 @@ type PlanRequest struct { VariableValues []*VariableValue `protobuf:"bytes,3,rep,name=variable_values,json=variableValues,proto3" json:"variable_values,omitempty"` ExternalAuthProviders []*ExternalAuthProvider `protobuf:"bytes,4,rep,name=external_auth_providers,json=externalAuthProviders,proto3" json:"external_auth_providers,omitempty"` PreviousParameterValues []*RichParameterValue `protobuf:"bytes,5,rep,name=previous_parameter_values,json=previousParameterValues,proto3" json:"previous_parameter_values,omitempty"` + // If true, the provisioner can safely assume the caller does not need the + // module files downloaded by the `terraform init` command. + // Ideally this boolean would be flipped in its truthy value, however for + // backwards compatibility reasons, the zero value should be the previous + // behavior of downloading the module files. + OmitModuleFiles bool `protobuf:"varint,6,opt,name=omit_module_files,json=omitModuleFiles,proto3" json:"omit_module_files,omitempty"` } func (x *PlanRequest) Reset() { @@ -3065,6 +3120,13 @@ func (x *PlanRequest) GetPreviousParameterValues() []*RichParameterValue { return nil } +func (x *PlanRequest) GetOmitModuleFiles() bool { + if x != nil { + return x.OmitModuleFiles + } + return false +} + // PlanComplete indicates a request to plan completed. type PlanComplete struct { state protoimpl.MessageState @@ -3081,6 +3143,7 @@ type PlanComplete struct { Plan []byte `protobuf:"bytes,9,opt,name=plan,proto3" json:"plan,omitempty"` ResourceReplacements []*ResourceReplacement `protobuf:"bytes,10,rep,name=resource_replacements,json=resourceReplacements,proto3" json:"resource_replacements,omitempty"` ModuleFiles []byte `protobuf:"bytes,11,opt,name=module_files,json=moduleFiles,proto3" json:"module_files,omitempty"` + ModuleFilesHash []byte `protobuf:"bytes,12,opt,name=module_files_hash,json=moduleFilesHash,proto3" json:"module_files_hash,omitempty"` } func (x *PlanComplete) Reset() { @@ -3185,6 +3248,13 @@ func (x *PlanComplete) GetModuleFiles() []byte { return nil } +func (x *PlanComplete) GetModuleFilesHash() []byte { + if x != nil { + return x.ModuleFilesHash + } + return nil +} + // ApplyRequest asks the provisioner to apply the changes. Apply MUST be preceded by a successful plan request/response // in the same Session. The plan data is not transmitted over the wire and is cached by the provisioner in the Session. type ApplyRequest struct { @@ -3590,6 +3660,8 @@ type Response struct { // *Response_Parse // *Response_Plan // *Response_Apply + // *Response_DataUpload + // *Response_ChunkPiece Type isResponse_Type `protobuf_oneof:"type"` } @@ -3660,6 +3732,20 @@ func (x *Response) GetApply() *ApplyComplete { return nil } +func (x *Response) GetDataUpload() *DataUpload { + if x, ok := x.GetType().(*Response_DataUpload); ok { + return x.DataUpload + } + return nil +} + +func (x *Response) GetChunkPiece() *ChunkPiece { + if x, ok := x.GetType().(*Response_ChunkPiece); ok { + return x.ChunkPiece + } + return nil +} + type isResponse_Type interface { isResponse_Type() } @@ -3680,6 +3766,14 @@ type Response_Apply struct { Apply *ApplyComplete `protobuf:"bytes,4,opt,name=apply,proto3,oneof"` } +type Response_DataUpload struct { + DataUpload *DataUpload `protobuf:"bytes,5,opt,name=data_upload,json=dataUpload,proto3,oneof"` +} + +type Response_ChunkPiece struct { + ChunkPiece *ChunkPiece `protobuf:"bytes,6,opt,name=chunk_piece,json=chunkPiece,proto3,oneof"` +} + func (*Response_Log) isResponse_Type() {} func (*Response_Parse) isResponse_Type() {} @@ -3688,6 +3782,151 @@ func (*Response_Plan) isResponse_Type() {} func (*Response_Apply) isResponse_Type() {} +func (*Response_DataUpload) isResponse_Type() {} + +func (*Response_ChunkPiece) isResponse_Type() {} + +type DataUpload struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UploadType DataUploadType `protobuf:"varint,1,opt,name=upload_type,json=uploadType,proto3,enum=provisioner.DataUploadType" json:"upload_type,omitempty"` + // data_hash is the sha256 of the payload to be uploaded. + // This is also used to uniquely identify the upload. + DataHash []byte `protobuf:"bytes,2,opt,name=data_hash,json=dataHash,proto3" json:"data_hash,omitempty"` + // file_size is the total size of the data being uploaded. + FileSize int64 `protobuf:"varint,3,opt,name=file_size,json=fileSize,proto3" json:"file_size,omitempty"` + // Number of chunks to be uploaded. + Chunks int32 `protobuf:"varint,4,opt,name=chunks,proto3" json:"chunks,omitempty"` +} + +func (x *DataUpload) Reset() { + *x = DataUpload{} + if protoimpl.UnsafeEnabled { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DataUpload) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DataUpload) ProtoMessage() {} + +func (x *DataUpload) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[41] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DataUpload.ProtoReflect.Descriptor instead. +func (*DataUpload) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{41} +} + +func (x *DataUpload) GetUploadType() DataUploadType { + if x != nil { + return x.UploadType + } + return DataUploadType_UPLOAD_TYPE_UNKNOWN +} + +func (x *DataUpload) GetDataHash() []byte { + if x != nil { + return x.DataHash + } + return nil +} + +func (x *DataUpload) GetFileSize() int64 { + if x != nil { + return x.FileSize + } + return 0 +} + +func (x *DataUpload) GetChunks() int32 { + if x != nil { + return x.Chunks + } + return 0 +} + +// ChunkPiece is used to stream over large files (over the 4mb limit). +type ChunkPiece struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` + // full_data_hash should match the hash from the original + // DataUpload message + FullDataHash []byte `protobuf:"bytes,2,opt,name=full_data_hash,json=fullDataHash,proto3" json:"full_data_hash,omitempty"` + PieceIndex int32 `protobuf:"varint,3,opt,name=piece_index,json=pieceIndex,proto3" json:"piece_index,omitempty"` +} + +func (x *ChunkPiece) Reset() { + *x = ChunkPiece{} + if protoimpl.UnsafeEnabled { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ChunkPiece) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChunkPiece) ProtoMessage() {} + +func (x *ChunkPiece) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[42] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ChunkPiece.ProtoReflect.Descriptor instead. +func (*ChunkPiece) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{42} +} + +func (x *ChunkPiece) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +func (x *ChunkPiece) GetFullDataHash() []byte { + if x != nil { + return x.FullDataHash + } + return nil +} + +func (x *ChunkPiece) GetPieceIndex() int32 { + if x != nil { + return x.PieceIndex + } + return 0 +} + type Agent_Metadata struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3704,7 +3943,7 @@ type Agent_Metadata struct { func (x *Agent_Metadata) Reset() { *x = Agent_Metadata{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[41] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3717,7 +3956,7 @@ func (x *Agent_Metadata) String() string { func (*Agent_Metadata) ProtoMessage() {} func (x *Agent_Metadata) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[41] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3789,7 +4028,7 @@ type Resource_Metadata struct { func (x *Resource_Metadata) Reset() { *x = Resource_Metadata{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[43] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3802,7 +4041,7 @@ func (x *Resource_Metadata) String() string { func (*Resource_Metadata) ProtoMessage() {} func (x *Resource_Metadata) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[43] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4280,7 +4519,7 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x61, 0x67, 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, 0x92, 0x03, 0x0a, 0x0b, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0xbe, 0x03, 0x0a, 0x0b, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, @@ -4305,153 +4544,187 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x17, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x93, 0x04, 0x0a, 0x0c, 0x50, 0x6c, - 0x61, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, - 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, - 0x73, 0x12, 0x61, 0x0a, 0x17, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, - 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x15, 0x65, - 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x18, - 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x69, - 0x6e, 0x67, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x07, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x72, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, - 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x74, 0x73, 0x18, 0x08, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, - 0x72, 0x2e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x52, 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x74, - 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x55, 0x0a, 0x15, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0a, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x61, - 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x14, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, - 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x0b, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x22, - 0x41, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x31, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x22, 0xbe, 0x02, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6d, 0x70, - 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, - 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, - 0x73, 0x12, 0x61, 0x0a, 0x17, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, - 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x15, 0x65, - 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x18, - 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x69, - 0x6e, 0x67, 0x73, 0x22, 0xfa, 0x01, 0x0a, 0x06, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x30, - 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x12, 0x2c, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x16, - 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1a, - 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, - 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, - 0x12, 0x2e, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x69, - 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x22, 0x0f, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0x8c, 0x02, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, - 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x48, 0x00, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x31, 0x0a, 0x05, - 0x70, 0x61, 0x72, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x12, - 0x2e, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, + 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x6d, 0x69, + 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x6f, 0x6d, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, + 0x46, 0x69, 0x6c, 0x65, 0x73, 0x22, 0xbf, 0x04, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, + 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x33, 0x0a, 0x09, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x12, 0x3a, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, + 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x61, 0x0a, + 0x17, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, + 0x12, 0x2d, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, + 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x12, + 0x2d, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4d, + 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x2d, + 0x0a, 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, + 0x65, 0x73, 0x65, 0x74, 0x52, 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x74, 0x73, 0x12, 0x12, 0x0a, + 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x70, 0x6c, 0x61, + 0x6e, 0x12, 0x55, 0x0a, 0x15, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, + 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x52, 0x14, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6c, + 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x6f, 0x64, 0x75, + 0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, + 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, + 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x48, 0x61, 0x73, 0x68, 0x22, 0x41, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x6c, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xbe, 0x02, 0x0a, 0x0d, 0x41, + 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3a, 0x0a, + 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, + 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x61, 0x0a, 0x17, 0x65, 0x78, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, + 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x0a, 0x07, + 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x69, 0x6d, 0x69, + 0x6e, 0x67, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x22, 0xfa, 0x01, 0x0a, 0x06, + 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2c, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x0f, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, + 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x02, 0x0a, 0x07, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x06, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x31, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, + 0x52, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, + 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x31, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x34, 0x0a, 0x06, 0x63, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xc9, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x32, 0x0a, 0x05, 0x70, + 0x61, 0x72, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x43, 0x6f, + 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x12, + 0x2f, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x6c, 0x61, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, - 0x31, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, - 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70, 0x70, - 0x6c, 0x79, 0x12, 0x34, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, - 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x22, 0xd1, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, - 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, - 0x6c, 0x6f, 0x67, 0x12, 0x32, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, - 0x52, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, - 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x32, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, - 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x6c, - 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x42, 0x06, 0x0a, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x2a, 0xa8, 0x01, 0x0a, 0x11, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x46, 0x6f, 0x72, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, - 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x4d, 0x5f, - 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x41, 0x44, 0x49, 0x4f, - 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x52, 0x4f, 0x50, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x03, - 0x12, 0x09, 0x0a, 0x05, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x54, - 0x45, 0x58, 0x54, 0x41, 0x52, 0x45, 0x41, 0x10, 0x05, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x4c, 0x49, - 0x44, 0x45, 0x52, 0x10, 0x06, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x42, 0x4f, - 0x58, 0x10, 0x07, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x57, 0x49, 0x54, 0x43, 0x48, 0x10, 0x08, 0x12, - 0x0d, 0x0a, 0x09, 0x54, 0x41, 0x47, 0x53, 0x45, 0x4c, 0x45, 0x43, 0x54, 0x10, 0x09, 0x12, 0x0f, - 0x0a, 0x0b, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x53, 0x45, 0x4c, 0x45, 0x43, 0x54, 0x10, 0x0a, 0x2a, - 0x3f, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x54, - 0x52, 0x41, 0x43, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, - 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, - 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, - 0x2a, 0x3b, 0x0a, 0x0f, 0x41, 0x70, 0x70, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, - 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x10, 0x00, 0x12, 0x11, - 0x0a, 0x0d, 0x41, 0x55, 0x54, 0x48, 0x45, 0x4e, 0x54, 0x49, 0x43, 0x41, 0x54, 0x45, 0x44, 0x10, - 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x10, 0x02, 0x2a, 0x35, 0x0a, - 0x09, 0x41, 0x70, 0x70, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x6e, 0x12, 0x0e, 0x0a, 0x06, 0x57, 0x49, - 0x4e, 0x44, 0x4f, 0x57, 0x10, 0x00, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x4c, - 0x49, 0x4d, 0x5f, 0x57, 0x49, 0x4e, 0x44, 0x4f, 0x57, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, - 0x41, 0x42, 0x10, 0x02, 0x2a, 0x37, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x09, 0x0a, 0x05, 0x53, - 0x54, 0x41, 0x52, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x01, - 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x53, 0x54, 0x52, 0x4f, 0x59, 0x10, 0x02, 0x2a, 0x3e, 0x0a, - 0x1b, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x08, 0x0a, 0x04, - 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, - 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x10, 0x02, 0x2a, 0x35, 0x0a, - 0x0b, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0b, 0x0a, 0x07, - 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, - 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, - 0x45, 0x44, 0x10, 0x02, 0x32, 0x49, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, - 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, - 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, - 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, + 0x12, 0x32, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, + 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, 0x61, + 0x70, 0x70, 0x6c, 0x79, 0x12, 0x3a, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x6c, + 0x6f, 0x61, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x55, 0x70, 0x6c, 0x6f, + 0x61, 0x64, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, + 0x12, 0x3a, 0x0a, 0x0b, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x5f, 0x70, 0x69, 0x65, 0x63, 0x65, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x69, 0x65, 0x63, 0x65, 0x48, 0x00, + 0x52, 0x0a, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x69, 0x65, 0x63, 0x65, 0x42, 0x06, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x22, 0x9c, 0x01, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x55, 0x70, 0x6c, + 0x6f, 0x61, 0x64, 0x12, 0x3c, 0x0a, 0x0b, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x64, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x64, 0x61, 0x74, 0x61, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1b, + 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, + 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x63, 0x68, 0x75, + 0x6e, 0x6b, 0x73, 0x22, 0x67, 0x0a, 0x0a, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x50, 0x69, 0x65, 0x63, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x64, 0x61, + 0x74, 0x61, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x66, + 0x75, 0x6c, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x70, + 0x69, 0x65, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x0a, 0x70, 0x69, 0x65, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x2a, 0xa8, 0x01, 0x0a, + 0x11, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x46, 0x6f, 0x72, 0x6d, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, + 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, + 0x09, 0x0a, 0x05, 0x52, 0x41, 0x44, 0x49, 0x4f, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x52, + 0x4f, 0x50, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x49, 0x4e, 0x50, 0x55, + 0x54, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x54, 0x45, 0x58, 0x54, 0x41, 0x52, 0x45, 0x41, 0x10, + 0x05, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x4c, 0x49, 0x44, 0x45, 0x52, 0x10, 0x06, 0x12, 0x0c, 0x0a, + 0x08, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x42, 0x4f, 0x58, 0x10, 0x07, 0x12, 0x0a, 0x0a, 0x06, 0x53, + 0x57, 0x49, 0x54, 0x43, 0x48, 0x10, 0x08, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x41, 0x47, 0x53, 0x45, + 0x4c, 0x45, 0x43, 0x54, 0x10, 0x09, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x53, + 0x45, 0x4c, 0x45, 0x43, 0x54, 0x10, 0x0a, 0x2a, 0x3f, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, + 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x00, 0x12, 0x09, + 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, + 0x4f, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, + 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x2a, 0x3b, 0x0a, 0x0f, 0x41, 0x70, 0x70, 0x53, + 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x4f, + 0x57, 0x4e, 0x45, 0x52, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x55, 0x54, 0x48, 0x45, 0x4e, + 0x54, 0x49, 0x43, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, 0x42, + 0x4c, 0x49, 0x43, 0x10, 0x02, 0x2a, 0x35, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x4f, 0x70, 0x65, 0x6e, + 0x49, 0x6e, 0x12, 0x0e, 0x0a, 0x06, 0x57, 0x49, 0x4e, 0x44, 0x4f, 0x57, 0x10, 0x00, 0x1a, 0x02, + 0x08, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x4c, 0x49, 0x4d, 0x5f, 0x57, 0x49, 0x4e, 0x44, 0x4f, + 0x57, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x41, 0x42, 0x10, 0x02, 0x2a, 0x37, 0x0a, 0x13, + 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x00, 0x12, 0x08, + 0x0a, 0x04, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x53, 0x54, + 0x52, 0x4f, 0x59, 0x10, 0x02, 0x2a, 0x3e, 0x0a, 0x1b, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, + 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, + 0x74, 0x61, 0x67, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0a, + 0x0a, 0x06, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x43, 0x4c, + 0x41, 0x49, 0x4d, 0x10, 0x02, 0x2a, 0x35, 0x0a, 0x0b, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x01, + 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x2a, 0x47, 0x0a, 0x0e, + 0x44, 0x61, 0x74, 0x61, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, + 0x0a, 0x13, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, + 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x55, 0x50, 0x4c, 0x4f, 0x41, + 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x55, 0x4c, 0x45, 0x5f, 0x46, 0x49, + 0x4c, 0x45, 0x53, 0x10, 0x01, 0x32, 0x49, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, + 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, + 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4466,8 +4739,8 @@ func file_provisionersdk_proto_provisioner_proto_rawDescGZIP() []byte { return file_provisionersdk_proto_provisioner_proto_rawDescData } -var file_provisionersdk_proto_provisioner_proto_enumTypes = make([]protoimpl.EnumInfo, 7) -var file_provisionersdk_proto_provisioner_proto_msgTypes = make([]protoimpl.MessageInfo, 45) +var file_provisionersdk_proto_provisioner_proto_enumTypes = make([]protoimpl.EnumInfo, 8) +var file_provisionersdk_proto_provisioner_proto_msgTypes = make([]protoimpl.MessageInfo, 47) var file_provisionersdk_proto_provisioner_proto_goTypes = []interface{}{ (ParameterFormType)(0), // 0: provisioner.ParameterFormType (LogLevel)(0), // 1: provisioner.LogLevel @@ -4476,117 +4749,123 @@ var file_provisionersdk_proto_provisioner_proto_goTypes = []interface{}{ (WorkspaceTransition)(0), // 4: provisioner.WorkspaceTransition (PrebuiltWorkspaceBuildStage)(0), // 5: provisioner.PrebuiltWorkspaceBuildStage (TimingState)(0), // 6: provisioner.TimingState - (*Empty)(nil), // 7: provisioner.Empty - (*TemplateVariable)(nil), // 8: provisioner.TemplateVariable - (*RichParameterOption)(nil), // 9: provisioner.RichParameterOption - (*RichParameter)(nil), // 10: provisioner.RichParameter - (*RichParameterValue)(nil), // 11: provisioner.RichParameterValue - (*ExpirationPolicy)(nil), // 12: provisioner.ExpirationPolicy - (*Prebuild)(nil), // 13: provisioner.Prebuild - (*Preset)(nil), // 14: provisioner.Preset - (*PresetParameter)(nil), // 15: provisioner.PresetParameter - (*ResourceReplacement)(nil), // 16: provisioner.ResourceReplacement - (*VariableValue)(nil), // 17: provisioner.VariableValue - (*Log)(nil), // 18: provisioner.Log - (*InstanceIdentityAuth)(nil), // 19: provisioner.InstanceIdentityAuth - (*ExternalAuthProviderResource)(nil), // 20: provisioner.ExternalAuthProviderResource - (*ExternalAuthProvider)(nil), // 21: provisioner.ExternalAuthProvider - (*Agent)(nil), // 22: provisioner.Agent - (*ResourcesMonitoring)(nil), // 23: provisioner.ResourcesMonitoring - (*MemoryResourceMonitor)(nil), // 24: provisioner.MemoryResourceMonitor - (*VolumeResourceMonitor)(nil), // 25: provisioner.VolumeResourceMonitor - (*DisplayApps)(nil), // 26: provisioner.DisplayApps - (*Env)(nil), // 27: provisioner.Env - (*Script)(nil), // 28: provisioner.Script - (*Devcontainer)(nil), // 29: provisioner.Devcontainer - (*App)(nil), // 30: provisioner.App - (*Healthcheck)(nil), // 31: provisioner.Healthcheck - (*Resource)(nil), // 32: provisioner.Resource - (*Module)(nil), // 33: provisioner.Module - (*Role)(nil), // 34: provisioner.Role - (*RunningAgentAuthToken)(nil), // 35: provisioner.RunningAgentAuthToken - (*Metadata)(nil), // 36: provisioner.Metadata - (*Config)(nil), // 37: provisioner.Config - (*ParseRequest)(nil), // 38: provisioner.ParseRequest - (*ParseComplete)(nil), // 39: provisioner.ParseComplete - (*PlanRequest)(nil), // 40: provisioner.PlanRequest - (*PlanComplete)(nil), // 41: provisioner.PlanComplete - (*ApplyRequest)(nil), // 42: provisioner.ApplyRequest - (*ApplyComplete)(nil), // 43: provisioner.ApplyComplete - (*Timing)(nil), // 44: provisioner.Timing - (*CancelRequest)(nil), // 45: provisioner.CancelRequest - (*Request)(nil), // 46: provisioner.Request - (*Response)(nil), // 47: provisioner.Response - (*Agent_Metadata)(nil), // 48: provisioner.Agent.Metadata - nil, // 49: provisioner.Agent.EnvEntry - (*Resource_Metadata)(nil), // 50: provisioner.Resource.Metadata - nil, // 51: provisioner.ParseComplete.WorkspaceTagsEntry - (*timestamppb.Timestamp)(nil), // 52: google.protobuf.Timestamp + (DataUploadType)(0), // 7: provisioner.DataUploadType + (*Empty)(nil), // 8: provisioner.Empty + (*TemplateVariable)(nil), // 9: provisioner.TemplateVariable + (*RichParameterOption)(nil), // 10: provisioner.RichParameterOption + (*RichParameter)(nil), // 11: provisioner.RichParameter + (*RichParameterValue)(nil), // 12: provisioner.RichParameterValue + (*ExpirationPolicy)(nil), // 13: provisioner.ExpirationPolicy + (*Prebuild)(nil), // 14: provisioner.Prebuild + (*Preset)(nil), // 15: provisioner.Preset + (*PresetParameter)(nil), // 16: provisioner.PresetParameter + (*ResourceReplacement)(nil), // 17: provisioner.ResourceReplacement + (*VariableValue)(nil), // 18: provisioner.VariableValue + (*Log)(nil), // 19: provisioner.Log + (*InstanceIdentityAuth)(nil), // 20: provisioner.InstanceIdentityAuth + (*ExternalAuthProviderResource)(nil), // 21: provisioner.ExternalAuthProviderResource + (*ExternalAuthProvider)(nil), // 22: provisioner.ExternalAuthProvider + (*Agent)(nil), // 23: provisioner.Agent + (*ResourcesMonitoring)(nil), // 24: provisioner.ResourcesMonitoring + (*MemoryResourceMonitor)(nil), // 25: provisioner.MemoryResourceMonitor + (*VolumeResourceMonitor)(nil), // 26: provisioner.VolumeResourceMonitor + (*DisplayApps)(nil), // 27: provisioner.DisplayApps + (*Env)(nil), // 28: provisioner.Env + (*Script)(nil), // 29: provisioner.Script + (*Devcontainer)(nil), // 30: provisioner.Devcontainer + (*App)(nil), // 31: provisioner.App + (*Healthcheck)(nil), // 32: provisioner.Healthcheck + (*Resource)(nil), // 33: provisioner.Resource + (*Module)(nil), // 34: provisioner.Module + (*Role)(nil), // 35: provisioner.Role + (*RunningAgentAuthToken)(nil), // 36: provisioner.RunningAgentAuthToken + (*Metadata)(nil), // 37: provisioner.Metadata + (*Config)(nil), // 38: provisioner.Config + (*ParseRequest)(nil), // 39: provisioner.ParseRequest + (*ParseComplete)(nil), // 40: provisioner.ParseComplete + (*PlanRequest)(nil), // 41: provisioner.PlanRequest + (*PlanComplete)(nil), // 42: provisioner.PlanComplete + (*ApplyRequest)(nil), // 43: provisioner.ApplyRequest + (*ApplyComplete)(nil), // 44: provisioner.ApplyComplete + (*Timing)(nil), // 45: provisioner.Timing + (*CancelRequest)(nil), // 46: provisioner.CancelRequest + (*Request)(nil), // 47: provisioner.Request + (*Response)(nil), // 48: provisioner.Response + (*DataUpload)(nil), // 49: provisioner.DataUpload + (*ChunkPiece)(nil), // 50: provisioner.ChunkPiece + (*Agent_Metadata)(nil), // 51: provisioner.Agent.Metadata + nil, // 52: provisioner.Agent.EnvEntry + (*Resource_Metadata)(nil), // 53: provisioner.Resource.Metadata + nil, // 54: provisioner.ParseComplete.WorkspaceTagsEntry + (*timestamppb.Timestamp)(nil), // 55: google.protobuf.Timestamp } var file_provisionersdk_proto_provisioner_proto_depIdxs = []int32{ - 9, // 0: provisioner.RichParameter.options:type_name -> provisioner.RichParameterOption + 10, // 0: provisioner.RichParameter.options:type_name -> provisioner.RichParameterOption 0, // 1: provisioner.RichParameter.form_type:type_name -> provisioner.ParameterFormType - 12, // 2: provisioner.Prebuild.expiration_policy:type_name -> provisioner.ExpirationPolicy - 15, // 3: provisioner.Preset.parameters:type_name -> provisioner.PresetParameter - 13, // 4: provisioner.Preset.prebuild:type_name -> provisioner.Prebuild + 13, // 2: provisioner.Prebuild.expiration_policy:type_name -> provisioner.ExpirationPolicy + 16, // 3: provisioner.Preset.parameters:type_name -> provisioner.PresetParameter + 14, // 4: provisioner.Preset.prebuild:type_name -> provisioner.Prebuild 1, // 5: provisioner.Log.level:type_name -> provisioner.LogLevel - 49, // 6: provisioner.Agent.env:type_name -> provisioner.Agent.EnvEntry - 30, // 7: provisioner.Agent.apps:type_name -> provisioner.App - 48, // 8: provisioner.Agent.metadata:type_name -> provisioner.Agent.Metadata - 26, // 9: provisioner.Agent.display_apps:type_name -> provisioner.DisplayApps - 28, // 10: provisioner.Agent.scripts:type_name -> provisioner.Script - 27, // 11: provisioner.Agent.extra_envs:type_name -> provisioner.Env - 23, // 12: provisioner.Agent.resources_monitoring:type_name -> provisioner.ResourcesMonitoring - 29, // 13: provisioner.Agent.devcontainers:type_name -> provisioner.Devcontainer - 24, // 14: provisioner.ResourcesMonitoring.memory:type_name -> provisioner.MemoryResourceMonitor - 25, // 15: provisioner.ResourcesMonitoring.volumes:type_name -> provisioner.VolumeResourceMonitor - 31, // 16: provisioner.App.healthcheck:type_name -> provisioner.Healthcheck + 52, // 6: provisioner.Agent.env:type_name -> provisioner.Agent.EnvEntry + 31, // 7: provisioner.Agent.apps:type_name -> provisioner.App + 51, // 8: provisioner.Agent.metadata:type_name -> provisioner.Agent.Metadata + 27, // 9: provisioner.Agent.display_apps:type_name -> provisioner.DisplayApps + 29, // 10: provisioner.Agent.scripts:type_name -> provisioner.Script + 28, // 11: provisioner.Agent.extra_envs:type_name -> provisioner.Env + 24, // 12: provisioner.Agent.resources_monitoring:type_name -> provisioner.ResourcesMonitoring + 30, // 13: provisioner.Agent.devcontainers:type_name -> provisioner.Devcontainer + 25, // 14: provisioner.ResourcesMonitoring.memory:type_name -> provisioner.MemoryResourceMonitor + 26, // 15: provisioner.ResourcesMonitoring.volumes:type_name -> provisioner.VolumeResourceMonitor + 32, // 16: provisioner.App.healthcheck:type_name -> provisioner.Healthcheck 2, // 17: provisioner.App.sharing_level:type_name -> provisioner.AppSharingLevel 3, // 18: provisioner.App.open_in:type_name -> provisioner.AppOpenIn - 22, // 19: provisioner.Resource.agents:type_name -> provisioner.Agent - 50, // 20: provisioner.Resource.metadata:type_name -> provisioner.Resource.Metadata + 23, // 19: provisioner.Resource.agents:type_name -> provisioner.Agent + 53, // 20: provisioner.Resource.metadata:type_name -> provisioner.Resource.Metadata 4, // 21: provisioner.Metadata.workspace_transition:type_name -> provisioner.WorkspaceTransition - 34, // 22: provisioner.Metadata.workspace_owner_rbac_roles:type_name -> provisioner.Role + 35, // 22: provisioner.Metadata.workspace_owner_rbac_roles:type_name -> provisioner.Role 5, // 23: provisioner.Metadata.prebuilt_workspace_build_stage:type_name -> provisioner.PrebuiltWorkspaceBuildStage - 35, // 24: provisioner.Metadata.running_agent_auth_tokens:type_name -> provisioner.RunningAgentAuthToken - 8, // 25: provisioner.ParseComplete.template_variables:type_name -> provisioner.TemplateVariable - 51, // 26: provisioner.ParseComplete.workspace_tags:type_name -> provisioner.ParseComplete.WorkspaceTagsEntry - 36, // 27: provisioner.PlanRequest.metadata:type_name -> provisioner.Metadata - 11, // 28: provisioner.PlanRequest.rich_parameter_values:type_name -> provisioner.RichParameterValue - 17, // 29: provisioner.PlanRequest.variable_values:type_name -> provisioner.VariableValue - 21, // 30: provisioner.PlanRequest.external_auth_providers:type_name -> provisioner.ExternalAuthProvider - 11, // 31: provisioner.PlanRequest.previous_parameter_values:type_name -> provisioner.RichParameterValue - 32, // 32: provisioner.PlanComplete.resources:type_name -> provisioner.Resource - 10, // 33: provisioner.PlanComplete.parameters:type_name -> provisioner.RichParameter - 20, // 34: provisioner.PlanComplete.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource - 44, // 35: provisioner.PlanComplete.timings:type_name -> provisioner.Timing - 33, // 36: provisioner.PlanComplete.modules:type_name -> provisioner.Module - 14, // 37: provisioner.PlanComplete.presets:type_name -> provisioner.Preset - 16, // 38: provisioner.PlanComplete.resource_replacements:type_name -> provisioner.ResourceReplacement - 36, // 39: provisioner.ApplyRequest.metadata:type_name -> provisioner.Metadata - 32, // 40: provisioner.ApplyComplete.resources:type_name -> provisioner.Resource - 10, // 41: provisioner.ApplyComplete.parameters:type_name -> provisioner.RichParameter - 20, // 42: provisioner.ApplyComplete.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource - 44, // 43: provisioner.ApplyComplete.timings:type_name -> provisioner.Timing - 52, // 44: provisioner.Timing.start:type_name -> google.protobuf.Timestamp - 52, // 45: provisioner.Timing.end:type_name -> google.protobuf.Timestamp + 36, // 24: provisioner.Metadata.running_agent_auth_tokens:type_name -> provisioner.RunningAgentAuthToken + 9, // 25: provisioner.ParseComplete.template_variables:type_name -> provisioner.TemplateVariable + 54, // 26: provisioner.ParseComplete.workspace_tags:type_name -> provisioner.ParseComplete.WorkspaceTagsEntry + 37, // 27: provisioner.PlanRequest.metadata:type_name -> provisioner.Metadata + 12, // 28: provisioner.PlanRequest.rich_parameter_values:type_name -> provisioner.RichParameterValue + 18, // 29: provisioner.PlanRequest.variable_values:type_name -> provisioner.VariableValue + 22, // 30: provisioner.PlanRequest.external_auth_providers:type_name -> provisioner.ExternalAuthProvider + 12, // 31: provisioner.PlanRequest.previous_parameter_values:type_name -> provisioner.RichParameterValue + 33, // 32: provisioner.PlanComplete.resources:type_name -> provisioner.Resource + 11, // 33: provisioner.PlanComplete.parameters:type_name -> provisioner.RichParameter + 21, // 34: provisioner.PlanComplete.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource + 45, // 35: provisioner.PlanComplete.timings:type_name -> provisioner.Timing + 34, // 36: provisioner.PlanComplete.modules:type_name -> provisioner.Module + 15, // 37: provisioner.PlanComplete.presets:type_name -> provisioner.Preset + 17, // 38: provisioner.PlanComplete.resource_replacements:type_name -> provisioner.ResourceReplacement + 37, // 39: provisioner.ApplyRequest.metadata:type_name -> provisioner.Metadata + 33, // 40: provisioner.ApplyComplete.resources:type_name -> provisioner.Resource + 11, // 41: provisioner.ApplyComplete.parameters:type_name -> provisioner.RichParameter + 21, // 42: provisioner.ApplyComplete.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource + 45, // 43: provisioner.ApplyComplete.timings:type_name -> provisioner.Timing + 55, // 44: provisioner.Timing.start:type_name -> google.protobuf.Timestamp + 55, // 45: provisioner.Timing.end:type_name -> google.protobuf.Timestamp 6, // 46: provisioner.Timing.state:type_name -> provisioner.TimingState - 37, // 47: provisioner.Request.config:type_name -> provisioner.Config - 38, // 48: provisioner.Request.parse:type_name -> provisioner.ParseRequest - 40, // 49: provisioner.Request.plan:type_name -> provisioner.PlanRequest - 42, // 50: provisioner.Request.apply:type_name -> provisioner.ApplyRequest - 45, // 51: provisioner.Request.cancel:type_name -> provisioner.CancelRequest - 18, // 52: provisioner.Response.log:type_name -> provisioner.Log - 39, // 53: provisioner.Response.parse:type_name -> provisioner.ParseComplete - 41, // 54: provisioner.Response.plan:type_name -> provisioner.PlanComplete - 43, // 55: provisioner.Response.apply:type_name -> provisioner.ApplyComplete - 46, // 56: provisioner.Provisioner.Session:input_type -> provisioner.Request - 47, // 57: provisioner.Provisioner.Session:output_type -> provisioner.Response - 57, // [57:58] is the sub-list for method output_type - 56, // [56:57] is the sub-list for method input_type - 56, // [56:56] is the sub-list for extension type_name - 56, // [56:56] is the sub-list for extension extendee - 0, // [0:56] is the sub-list for field type_name + 38, // 47: provisioner.Request.config:type_name -> provisioner.Config + 39, // 48: provisioner.Request.parse:type_name -> provisioner.ParseRequest + 41, // 49: provisioner.Request.plan:type_name -> provisioner.PlanRequest + 43, // 50: provisioner.Request.apply:type_name -> provisioner.ApplyRequest + 46, // 51: provisioner.Request.cancel:type_name -> provisioner.CancelRequest + 19, // 52: provisioner.Response.log:type_name -> provisioner.Log + 40, // 53: provisioner.Response.parse:type_name -> provisioner.ParseComplete + 42, // 54: provisioner.Response.plan:type_name -> provisioner.PlanComplete + 44, // 55: provisioner.Response.apply:type_name -> provisioner.ApplyComplete + 49, // 56: provisioner.Response.data_upload:type_name -> provisioner.DataUpload + 50, // 57: provisioner.Response.chunk_piece:type_name -> provisioner.ChunkPiece + 7, // 58: provisioner.DataUpload.upload_type:type_name -> provisioner.DataUploadType + 47, // 59: provisioner.Provisioner.Session:input_type -> provisioner.Request + 48, // 60: provisioner.Provisioner.Session:output_type -> provisioner.Response + 60, // [60:61] is the sub-list for method output_type + 59, // [59:60] is the sub-list for method input_type + 59, // [59:59] is the sub-list for extension type_name + 59, // [59:59] is the sub-list for extension extendee + 0, // [0:59] is the sub-list for field type_name } func init() { file_provisionersdk_proto_provisioner_proto_init() } @@ -5088,7 +5367,19 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } file_provisionersdk_proto_provisioner_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Agent_Metadata); i { + switch v := v.(*DataUpload); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_provisionersdk_proto_provisioner_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ChunkPiece); i { case 0: return &v.state case 1: @@ -5100,6 +5391,18 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } file_provisionersdk_proto_provisioner_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Agent_Metadata); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_provisionersdk_proto_provisioner_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Resource_Metadata); i { case 0: return &v.state @@ -5129,14 +5432,16 @@ func file_provisionersdk_proto_provisioner_proto_init() { (*Response_Parse)(nil), (*Response_Plan)(nil), (*Response_Apply)(nil), + (*Response_DataUpload)(nil), + (*Response_ChunkPiece)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_provisionersdk_proto_provisioner_proto_rawDesc, - NumEnums: 7, - NumMessages: 45, + NumEnums: 8, + NumMessages: 47, NumExtensions: 0, NumServices: 1, }, diff --git a/provisionersdk/proto/provisioner.proto b/provisionersdk/proto/provisioner.proto index b305f5d494d8f..a74cba40256cb 100644 --- a/provisionersdk/proto/provisioner.proto +++ b/provisionersdk/proto/provisioner.proto @@ -366,6 +366,13 @@ message PlanRequest { repeated VariableValue variable_values = 3; repeated ExternalAuthProvider external_auth_providers = 4; repeated RichParameterValue previous_parameter_values = 5; + + // If true, the provisioner can safely assume the caller does not need the + // module files downloaded by the `terraform init` command. + // Ideally this boolean would be flipped in its truthy value, however for + // backwards compatibility reasons, the zero value should be the previous + // behavior of downloading the module files. + bool omit_module_files = 6; } // PlanComplete indicates a request to plan completed. @@ -380,6 +387,7 @@ message PlanComplete { bytes plan = 9; repeated ResourceReplacement resource_replacements = 10; bytes module_files = 11; + bytes module_files_hash = 12; } // ApplyRequest asks the provisioner to apply the changes. Apply MUST be preceded by a successful plan request/response @@ -433,9 +441,39 @@ message Response { ParseComplete parse = 2; PlanComplete plan = 3; ApplyComplete apply = 4; + DataUpload data_upload = 5; + ChunkPiece chunk_piece = 6; } } +enum DataUploadType { + UPLOAD_TYPE_UNKNOWN = 0; + // UPLOAD_TYPE_MODULE_FILES is used to stream over terraform module files. + // These files are located in `.terraform/modules` and are used for dynamic + // parameters. + UPLOAD_TYPE_MODULE_FILES = 1; +} + +message DataUpload { + DataUploadType upload_type = 1; + // data_hash is the sha256 of the payload to be uploaded. + // This is also used to uniquely identify the upload. + bytes data_hash = 2; + // file_size is the total size of the data being uploaded. + int64 file_size = 3; + // Number of chunks to be uploaded. + int32 chunks = 4; +} + +// ChunkPiece is used to stream over large files (over the 4mb limit). +message ChunkPiece { + bytes data = 1; + // full_data_hash should match the hash from the original + // DataUpload message + bytes full_data_hash = 2; + int32 piece_index = 3; +} + service Provisioner { // Session represents provisioning a single template import or workspace. The daemon always sends Config followed // by one of the requests (ParseRequest, PlanRequest, ApplyRequest). The provisioner should respond with a stream diff --git a/provisionersdk/session.go b/provisionersdk/session.go index fe6e3e2ca1f97..3fd23628854e5 100644 --- a/provisionersdk/session.go +++ b/provisionersdk/session.go @@ -17,6 +17,9 @@ import ( "golang.org/x/xerrors" "cdr.dev/slog" + "github.com/coder/coder/v2/codersdk/drpcsdk" + + protobuf "google.golang.org/protobuf/proto" "github.com/coder/coder/v2/provisionersdk/proto" ) @@ -161,6 +164,33 @@ func (s *Session) handleRequests() error { return err } resp.Type = &proto.Response_Plan{Plan: complete} + + if protobuf.Size(resp) > drpcsdk.MaxMessageSize { + // It is likely the modules that is pushing the message size over the limit. + // Send the modules over a stream of messages instead. + s.Logger.Info(s.Context(), "plan response too large, sending modules as stream", + slog.F("size_bytes", len(complete.ModuleFiles)), + ) + dataUp, chunks := proto.BytesToDataUpload(proto.DataUploadType_UPLOAD_TYPE_MODULE_FILES, complete.ModuleFiles) + + complete.ModuleFiles = nil // sent over the stream + complete.ModuleFilesHash = dataUp.DataHash + resp.Type = &proto.Response_Plan{Plan: complete} + + err := s.stream.Send(&proto.Response{Type: &proto.Response_DataUpload{DataUpload: dataUp}}) + if err != nil { + complete.Error = fmt.Sprintf("send data upload: %s", err.Error()) + } else { + for i, chunk := range chunks { + err := s.stream.Send(&proto.Response{Type: &proto.Response_ChunkPiece{ChunkPiece: chunk}}) + if err != nil { + complete.Error = fmt.Sprintf("send data piece upload %d/%d: %s", i, dataUp.Chunks, err.Error()) + break + } + } + } + } + if complete.Error == "" { planned = true } diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index 0d6c10df500b0..cc91984ae592f 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -584,6 +584,7 @@ const createTemplateVersionTar = async ( resourceReplacements: [], plan: emptyPlan, moduleFiles: new Uint8Array(), + moduleFilesHash: new Uint8Array(), }, }; }); @@ -711,6 +712,7 @@ const createTemplateVersionTar = async ( resourceReplacements: [], plan: emptyPlan, moduleFiles: new Uint8Array(), + moduleFilesHash: new Uint8Array(), ...response.plan, } as PlanComplete; response.plan.resources = response.plan.resources?.map(fillResource); diff --git a/site/e2e/provisionerGenerated.ts b/site/e2e/provisionerGenerated.ts index f5f3d1f52c5c6..e94c8df1cc9ee 100644 --- a/site/e2e/provisionerGenerated.ts +++ b/site/e2e/provisionerGenerated.ts @@ -70,6 +70,17 @@ export enum TimingState { UNRECOGNIZED = -1, } +export enum DataUploadType { + UPLOAD_TYPE_UNKNOWN = 0, + /** + * UPLOAD_TYPE_MODULE_FILES - UPLOAD_TYPE_MODULE_FILES is used to stream over terraform module files. + * These files are located in `.terraform/modules` and are used for dynamic + * parameters. + */ + UPLOAD_TYPE_MODULE_FILES = 1, + UNRECOGNIZED = -1, +} + /** Empty indicates a successful request/response. */ export interface Empty { } @@ -394,6 +405,14 @@ export interface PlanRequest { variableValues: VariableValue[]; externalAuthProviders: ExternalAuthProvider[]; previousParameterValues: RichParameterValue[]; + /** + * If true, the provisioner can safely assume the caller does not need the + * module files downloaded by the `terraform init` command. + * Ideally this boolean would be flipped in its truthy value, however for + * backwards compatibility reasons, the zero value should be the previous + * behavior of downloading the module files. + */ + omitModuleFiles: boolean; } /** PlanComplete indicates a request to plan completed. */ @@ -408,6 +427,7 @@ export interface PlanComplete { plan: Uint8Array; resourceReplacements: ResourceReplacement[]; moduleFiles: Uint8Array; + moduleFilesHash: Uint8Array; } /** @@ -455,6 +475,32 @@ export interface Response { parse?: ParseComplete | undefined; plan?: PlanComplete | undefined; apply?: ApplyComplete | undefined; + dataUpload?: DataUpload | undefined; + chunkPiece?: ChunkPiece | undefined; +} + +export interface DataUpload { + uploadType: DataUploadType; + /** + * data_hash is the sha256 of the payload to be uploaded. + * This is also used to uniquely identify the upload. + */ + dataHash: Uint8Array; + /** file_size is the total size of the data being uploaded. */ + fileSize: number; + /** Number of chunks to be uploaded. */ + chunks: number; +} + +/** ChunkPiece is used to stream over large files (over the 4mb limit). */ +export interface ChunkPiece { + data: Uint8Array; + /** + * full_data_hash should match the hash from the original + * DataUpload message + */ + fullDataHash: Uint8Array; + pieceIndex: number; } export const Empty = { @@ -1206,6 +1252,9 @@ export const PlanRequest = { for (const v of message.previousParameterValues) { RichParameterValue.encode(v!, writer.uint32(42).fork()).ldelim(); } + if (message.omitModuleFiles === true) { + writer.uint32(48).bool(message.omitModuleFiles); + } return writer; }, }; @@ -1242,6 +1291,9 @@ export const PlanComplete = { if (message.moduleFiles.length !== 0) { writer.uint32(90).bytes(message.moduleFiles); } + if (message.moduleFilesHash.length !== 0) { + writer.uint32(98).bytes(message.moduleFilesHash); + } return writer; }, }; @@ -1347,6 +1399,45 @@ export const Response = { if (message.apply !== undefined) { ApplyComplete.encode(message.apply, writer.uint32(34).fork()).ldelim(); } + if (message.dataUpload !== undefined) { + DataUpload.encode(message.dataUpload, writer.uint32(42).fork()).ldelim(); + } + if (message.chunkPiece !== undefined) { + ChunkPiece.encode(message.chunkPiece, writer.uint32(50).fork()).ldelim(); + } + return writer; + }, +}; + +export const DataUpload = { + encode(message: DataUpload, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.uploadType !== 0) { + writer.uint32(8).int32(message.uploadType); + } + if (message.dataHash.length !== 0) { + writer.uint32(18).bytes(message.dataHash); + } + if (message.fileSize !== 0) { + writer.uint32(24).int64(message.fileSize); + } + if (message.chunks !== 0) { + writer.uint32(32).int32(message.chunks); + } + return writer; + }, +}; + +export const ChunkPiece = { + encode(message: ChunkPiece, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.data.length !== 0) { + writer.uint32(10).bytes(message.data); + } + if (message.fullDataHash.length !== 0) { + writer.uint32(18).bytes(message.fullDataHash); + } + if (message.pieceIndex !== 0) { + writer.uint32(24).int32(message.pieceIndex); + } return writer; }, };