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; }, }; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy