From 935719c6729926ff8dc461c3f84873c637bdbf13 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Wed, 23 Aug 2023 08:17:42 +0000 Subject: [PATCH 01/13] refactor provisionersdk protocol Signed-off-by: Spike Curtis --- Makefile | 8 +- provisionerd/proto/provisionerd.pb.go | 390 +++-- provisionerd/proto/provisionerd.proto | 6 +- provisionersdk/proto/provisioner.pb.go | 1417 +++++++++---------- provisionersdk/proto/provisioner.proto | 163 ++- provisionersdk/proto/provisioner_drpc.pb.go | 118 +- 6 files changed, 997 insertions(+), 1105 deletions(-) diff --git a/Makefile b/Makefile index c249fbd8c70ce..c687ebc14190b 100644 --- a/Makefile +++ b/Makefile @@ -456,10 +456,10 @@ DB_GEN_FILES := \ # all gen targets should be added here and to gen/mark-fresh gen: \ - coderd/database/dump.sql \ - $(DB_GEN_FILES) \ provisionersdk/proto/provisioner.pb.go \ provisionerd/proto/provisionerd.pb.go \ + coderd/database/dump.sql \ + $(DB_GEN_FILES) \ site/src/api/typesGenerated.ts \ coderd/rbac/object_gen.go \ docs/admin/prometheus.md \ @@ -478,10 +478,10 @@ gen: \ # used during releases so we don't run generation scripts. gen/mark-fresh: files="\ - coderd/database/dump.sql \ - $(DB_GEN_FILES) \ provisionersdk/proto/provisioner.pb.go \ provisionerd/proto/provisionerd.pb.go \ + coderd/database/dump.sql \ + $(DB_GEN_FILES) \ site/src/api/typesGenerated.ts \ coderd/rbac/object_gen.go \ docs/admin/prometheus.md \ diff --git a/provisionerd/proto/provisionerd.pb.go b/provisionerd/proto/provisionerd.pb.go index 7d949b9c9c2f0..a2843bf929c42 100644 --- a/provisionerd/proto/provisionerd.pb.go +++ b/provisionerd/proto/provisionerd.pb.go @@ -819,7 +819,7 @@ type AcquiredJob_WorkspaceBuild struct { RichParameterValues []*proto.RichParameterValue `protobuf:"bytes,4,rep,name=rich_parameter_values,json=richParameterValues,proto3" json:"rich_parameter_values,omitempty"` VariableValues []*proto.VariableValue `protobuf:"bytes,5,rep,name=variable_values,json=variableValues,proto3" json:"variable_values,omitempty"` GitAuthProviders []*proto.GitAuthProvider `protobuf:"bytes,6,rep,name=git_auth_providers,json=gitAuthProviders,proto3" json:"git_auth_providers,omitempty"` - Metadata *proto.Provision_Metadata `protobuf:"bytes,7,opt,name=metadata,proto3" json:"metadata,omitempty"` + Metadata *proto.Metadata `protobuf:"bytes,7,opt,name=metadata,proto3" json:"metadata,omitempty"` State []byte `protobuf:"bytes,8,opt,name=state,proto3" json:"state,omitempty"` LogLevel string `protobuf:"bytes,9,opt,name=log_level,json=logLevel,proto3" json:"log_level,omitempty"` } @@ -891,7 +891,7 @@ func (x *AcquiredJob_WorkspaceBuild) GetGitAuthProviders() []*proto.GitAuthProvi return nil } -func (x *AcquiredJob_WorkspaceBuild) GetMetadata() *proto.Provision_Metadata { +func (x *AcquiredJob_WorkspaceBuild) GetMetadata() *proto.Metadata { if x != nil { return x.Metadata } @@ -917,8 +917,8 @@ type AcquiredJob_TemplateImport struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Metadata *proto.Provision_Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` - UserVariableValues []*proto.VariableValue `protobuf:"bytes,2,rep,name=user_variable_values,json=userVariableValues,proto3" json:"user_variable_values,omitempty"` + Metadata *proto.Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` + UserVariableValues []*proto.VariableValue `protobuf:"bytes,2,rep,name=user_variable_values,json=userVariableValues,proto3" json:"user_variable_values,omitempty"` } func (x *AcquiredJob_TemplateImport) Reset() { @@ -953,7 +953,7 @@ func (*AcquiredJob_TemplateImport) Descriptor() ([]byte, []int) { return file_provisionerd_proto_provisionerd_proto_rawDescGZIP(), []int{1, 1} } -func (x *AcquiredJob_TemplateImport) GetMetadata() *proto.Provision_Metadata { +func (x *AcquiredJob_TemplateImport) GetMetadata() *proto.Metadata { if x != nil { return x.Metadata } @@ -974,7 +974,7 @@ type AcquiredJob_TemplateDryRun struct { RichParameterValues []*proto.RichParameterValue `protobuf:"bytes,2,rep,name=rich_parameter_values,json=richParameterValues,proto3" json:"rich_parameter_values,omitempty"` VariableValues []*proto.VariableValue `protobuf:"bytes,3,rep,name=variable_values,json=variableValues,proto3" json:"variable_values,omitempty"` - Metadata *proto.Provision_Metadata `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"` + Metadata *proto.Metadata `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"` } func (x *AcquiredJob_TemplateDryRun) Reset() { @@ -1023,7 +1023,7 @@ func (x *AcquiredJob_TemplateDryRun) GetVariableValues() []*proto.VariableValue return nil } -func (x *AcquiredJob_TemplateDryRun) GetMetadata() *proto.Provision_Metadata { +func (x *AcquiredJob_TemplateDryRun) GetMetadata() *proto.Metadata { if x != nil { return x.Metadata } @@ -1335,7 +1335,7 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{ 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x1a, 0x26, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x07, 0x0a, - 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xab, 0x0b, 0x0a, 0x0b, 0x41, 0x63, 0x71, 0x75, 0x69, + 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x8d, 0x0b, 0x0a, 0x0b, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, @@ -1368,7 +1368,7 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{ 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x63, 0x65, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0xc1, 0x03, 0x0a, 0x0e, 0x57, 0x6f, 0x72, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0xb7, 0x03, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, @@ -1389,193 +1389,191 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{ 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x47, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x10, 0x67, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x6f, 0x67, - 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, - 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x1a, 0x9b, 0x01, 0x0a, - 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, - 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 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, 0x02, 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, 0x1a, 0xed, 0x01, 0x0a, 0x0e, 0x54, - 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x53, 0x0a, - 0x15, 0x72, 0x69, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 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, 0x13, 0x72, - 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x73, 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, 0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x1a, 0x40, 0x0a, 0x12, 0x54, 0x72, - 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x06, 0x0a, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x22, 0xa5, 0x03, 0x0a, 0x09, 0x46, 0x61, 0x69, 0x6c, 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, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, - 0x51, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x62, 0x75, 0x69, - 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, - 0x62, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, - 0x48, 0x00, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, - 0x6c, 0x64, 0x12, 0x51, 0x0a, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x69, - 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x65, - 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, - 0x6f, 0x72, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, - 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x52, 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, - 0x65, 0x5f, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, - 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x07, 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, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x1b, 0x0a, 0x09, 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x4a, 0x04, 0x08, 0x03, + 0x10, 0x04, 0x1a, 0x91, 0x01, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, + 0x6d, 0x70, 0x6f, 0x72, 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, 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, 0x02, 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, 0x1a, 0xe3, 0x01, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x53, 0x0a, 0x15, 0x72, 0x69, 0x63, + 0x68, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 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, 0x13, 0x72, 0x69, 0x63, 0x68, 0x50, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 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, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x04, 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, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x1a, 0x40, 0x0a, 0x12, + 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x06, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xa5, 0x03, 0x0a, 0x09, 0x46, 0x61, 0x69, 0x6c, 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, 0x14, 0x0a, 0x05, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x12, 0x51, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x62, + 0x75, 0x69, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, + 0x4a, 0x6f, 0x62, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, + 0x6c, 0x64, 0x48, 0x00, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, + 0x75, 0x69, 0x6c, 0x64, 0x12, 0x51, 0x0a, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, + 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, 0x61, 0x69, + 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, + 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, + 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x52, 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x74, 0x65, 0x5f, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, + 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x1a, 0x26, 0x0a, 0x0e, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, + 0x74, 0x65, 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, 0xd8, + 0x05, 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, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x29, 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, 0x2e, 0x57, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x48, 0x00, 0x52, 0x0e, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x54, 0x0a, 0x0f, + 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 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, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, + 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, + 0x72, 0x74, 0x12, 0x55, 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x64, + 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 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, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, - 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x1a, 0x26, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, - 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, 0xd8, 0x05, 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, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 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, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x48, 0x00, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x54, 0x0a, 0x0f, 0x74, 0x65, - 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x29, 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, 0x2e, - 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x48, 0x00, - 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, - 0x12, 0x55, 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x72, 0x79, - 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 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, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, - 0x72, 0x79, 0x52, 0x75, 0x6e, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, - 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x1a, 0x5b, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, - 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x1a, 0x5b, 0x0a, 0x0e, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x65, 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, 0x1a, 0x81, 0x02, 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, 0x72, - 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x1a, 0x81, 0x02, 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, 0x72, 0x2e, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3c, 0x0a, 0x0e, 0x73, 0x74, 0x6f, 0x70, 0x5f, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3c, 0x0a, 0x0e, 0x73, 0x74, 0x6f, + 0x70, 0x5f, 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, 0x0d, 0x73, 0x74, 0x6f, 0x70, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x72, 0x69, 0x63, 0x68, 0x5f, + 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, 0x0e, 0x72, 0x69, + 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x2c, 0x0a, 0x12, + 0x67, 0x69, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x67, 0x69, 0x74, 0x41, 0x75, 0x74, + 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x1a, 0x45, 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, 0x0d, 0x73, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x72, 0x69, 0x63, 0x68, 0x5f, 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, 0x0e, 0x72, 0x69, 0x63, 0x68, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x69, - 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x67, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x1a, 0x45, 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, 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, 0x8a, 0x02, 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, 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, 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, - 0xec, 0x02, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x44, - 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x3c, 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, 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, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 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, 0x8a, 0x02, 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, 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, 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, 0xec, 0x02, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x3c, 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, 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, + 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, + 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 ( @@ -1618,7 +1616,7 @@ var file_provisionerd_proto_provisionerd_proto_goTypes = []interface{}{ (*proto.VariableValue)(nil), // 22: provisioner.VariableValue (*proto.RichParameterValue)(nil), // 23: provisioner.RichParameterValue (*proto.GitAuthProvider)(nil), // 24: provisioner.GitAuthProvider - (*proto.Provision_Metadata)(nil), // 25: provisioner.Provision.Metadata + (*proto.Metadata)(nil), // 25: provisioner.Metadata (*proto.Resource)(nil), // 26: provisioner.Resource (*proto.RichParameter)(nil), // 27: provisioner.RichParameter } @@ -1642,12 +1640,12 @@ var file_provisionerd_proto_provisionerd_proto_depIdxs = []int32{ 23, // 16: provisionerd.AcquiredJob.WorkspaceBuild.rich_parameter_values:type_name -> provisioner.RichParameterValue 22, // 17: provisionerd.AcquiredJob.WorkspaceBuild.variable_values:type_name -> provisioner.VariableValue 24, // 18: provisionerd.AcquiredJob.WorkspaceBuild.git_auth_providers:type_name -> provisioner.GitAuthProvider - 25, // 19: provisionerd.AcquiredJob.WorkspaceBuild.metadata:type_name -> provisioner.Provision.Metadata - 25, // 20: provisionerd.AcquiredJob.TemplateImport.metadata:type_name -> provisioner.Provision.Metadata + 25, // 19: provisionerd.AcquiredJob.WorkspaceBuild.metadata:type_name -> provisioner.Metadata + 25, // 20: provisionerd.AcquiredJob.TemplateImport.metadata:type_name -> provisioner.Metadata 22, // 21: provisionerd.AcquiredJob.TemplateImport.user_variable_values:type_name -> provisioner.VariableValue 23, // 22: provisionerd.AcquiredJob.TemplateDryRun.rich_parameter_values:type_name -> provisioner.RichParameterValue 22, // 23: provisionerd.AcquiredJob.TemplateDryRun.variable_values:type_name -> provisioner.VariableValue - 25, // 24: provisionerd.AcquiredJob.TemplateDryRun.metadata:type_name -> provisioner.Provision.Metadata + 25, // 24: provisionerd.AcquiredJob.TemplateDryRun.metadata:type_name -> provisioner.Metadata 26, // 25: provisionerd.CompletedJob.WorkspaceBuild.resources:type_name -> provisioner.Resource 26, // 26: provisionerd.CompletedJob.TemplateImport.start_resources:type_name -> provisioner.Resource 26, // 27: provisionerd.CompletedJob.TemplateImport.stop_resources:type_name -> provisioner.Resource diff --git a/provisionerd/proto/provisionerd.proto b/provisionerd/proto/provisionerd.proto index 2a417f48a0cc7..e2cc0b361f87a 100644 --- a/provisionerd/proto/provisionerd.proto +++ b/provisionerd/proto/provisionerd.proto @@ -19,12 +19,12 @@ message AcquiredJob { repeated provisioner.RichParameterValue rich_parameter_values = 4; repeated provisioner.VariableValue variable_values = 5; repeated provisioner.GitAuthProvider git_auth_providers = 6; - provisioner.Provision.Metadata metadata = 7; + provisioner.Metadata metadata = 7; bytes state = 8; string log_level = 9; } message TemplateImport { - provisioner.Provision.Metadata metadata = 1; + provisioner.Metadata metadata = 1; repeated provisioner.VariableValue user_variable_values = 2; } message TemplateDryRun { @@ -32,7 +32,7 @@ message AcquiredJob { repeated provisioner.RichParameterValue rich_parameter_values = 2; repeated provisioner.VariableValue variable_values = 3; - provisioner.Provision.Metadata metadata = 4; + provisioner.Metadata metadata = 4; } string job_id = 1; diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go index c334ad13a5ac9..f7f13b19f5b2e 100644 --- a/provisionersdk/proto/provisioner.pb.go +++ b/provisionersdk/proto/provisioner.pb.go @@ -125,6 +125,7 @@ func (AppSharingLevel) EnumDescriptor() ([]byte, []int) { return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{1} } +// WorkspaceTransition is the desired outcome of a build type WorkspaceTransition int32 const ( @@ -1313,15 +1314,27 @@ func (x *Resource) GetDailyCost() int32 { return 0 } -// Parse consumes source-code from a directory to produce inputs. -type Parse struct { +// Metadata is information about a workspace used in the execution of a build +type Metadata struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + CoderUrl string `protobuf:"bytes,1,opt,name=coder_url,json=coderUrl,proto3" json:"coder_url,omitempty"` + WorkspaceTransition WorkspaceTransition `protobuf:"varint,2,opt,name=workspace_transition,json=workspaceTransition,proto3,enum=provisioner.WorkspaceTransition" json:"workspace_transition,omitempty"` + WorkspaceName string `protobuf:"bytes,3,opt,name=workspace_name,json=workspaceName,proto3" json:"workspace_name,omitempty"` + WorkspaceOwner string `protobuf:"bytes,4,opt,name=workspace_owner,json=workspaceOwner,proto3" json:"workspace_owner,omitempty"` + WorkspaceId string `protobuf:"bytes,5,opt,name=workspace_id,json=workspaceId,proto3" json:"workspace_id,omitempty"` + WorkspaceOwnerId string `protobuf:"bytes,6,opt,name=workspace_owner_id,json=workspaceOwnerId,proto3" json:"workspace_owner_id,omitempty"` + WorkspaceOwnerEmail string `protobuf:"bytes,7,opt,name=workspace_owner_email,json=workspaceOwnerEmail,proto3" json:"workspace_owner_email,omitempty"` + TemplateName string `protobuf:"bytes,8,opt,name=template_name,json=templateName,proto3" json:"template_name,omitempty"` + TemplateVersion string `protobuf:"bytes,9,opt,name=template_version,json=templateVersion,proto3" json:"template_version,omitempty"` + WorkspaceOwnerOidcAccessToken string `protobuf:"bytes,10,opt,name=workspace_owner_oidc_access_token,json=workspaceOwnerOidcAccessToken,proto3" json:"workspace_owner_oidc_access_token,omitempty"` + WorkspaceOwnerSessionToken string `protobuf:"bytes,11,opt,name=workspace_owner_session_token,json=workspaceOwnerSessionToken,proto3" json:"workspace_owner_session_token,omitempty"` } -func (x *Parse) Reset() { - *x = Parse{} +func (x *Metadata) Reset() { + *x = Metadata{} if protoimpl.UnsafeEnabled { mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1329,13 +1342,13 @@ func (x *Parse) Reset() { } } -func (x *Parse) String() string { +func (x *Metadata) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Parse) ProtoMessage() {} +func (*Metadata) ProtoMessage() {} -func (x *Parse) ProtoReflect() protoreflect.Message { +func (x *Metadata) ProtoReflect() protoreflect.Message { mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1347,158 +1360,118 @@ func (x *Parse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Parse.ProtoReflect.Descriptor instead. -func (*Parse) Descriptor() ([]byte, []int) { +// Deprecated: Use Metadata.ProtoReflect.Descriptor instead. +func (*Metadata) Descriptor() ([]byte, []int) { return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{13} } -// Provision consumes source-code from a directory to produce resources. -// Exactly one of Plan or Apply must be provided in a single session. -type Provision struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *Provision) Reset() { - *x = Provision{} - if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) +func (x *Metadata) GetCoderUrl() string { + if x != nil { + return x.CoderUrl } + return "" } -func (x *Provision) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Provision) ProtoMessage() {} - -func (x *Provision) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms +func (x *Metadata) GetWorkspaceTransition() WorkspaceTransition { + if x != nil { + return x.WorkspaceTransition } - return mi.MessageOf(x) -} - -// Deprecated: Use Provision.ProtoReflect.Descriptor instead. -func (*Provision) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{14} -} - -type Agent_Metadata struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` - Script string `protobuf:"bytes,3,opt,name=script,proto3" json:"script,omitempty"` - Interval int64 `protobuf:"varint,4,opt,name=interval,proto3" json:"interval,omitempty"` - Timeout int64 `protobuf:"varint,5,opt,name=timeout,proto3" json:"timeout,omitempty"` + return WorkspaceTransition_START } -func (x *Agent_Metadata) Reset() { - *x = Agent_Metadata{} - if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) +func (x *Metadata) GetWorkspaceName() string { + if x != nil { + return x.WorkspaceName } + return "" } -func (x *Agent_Metadata) String() string { - return protoimpl.X.MessageStringOf(x) +func (x *Metadata) GetWorkspaceOwner() string { + if x != nil { + return x.WorkspaceOwner + } + return "" } -func (*Agent_Metadata) ProtoMessage() {} - -func (x *Agent_Metadata) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms +func (x *Metadata) GetWorkspaceId() string { + if x != nil { + return x.WorkspaceId } - return mi.MessageOf(x) + return "" } -// Deprecated: Use Agent_Metadata.ProtoReflect.Descriptor instead. -func (*Agent_Metadata) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{9, 0} +func (x *Metadata) GetWorkspaceOwnerId() string { + if x != nil { + return x.WorkspaceOwnerId + } + return "" } -func (x *Agent_Metadata) GetKey() string { +func (x *Metadata) GetWorkspaceOwnerEmail() string { if x != nil { - return x.Key + return x.WorkspaceOwnerEmail } return "" } -func (x *Agent_Metadata) GetDisplayName() string { +func (x *Metadata) GetTemplateName() string { if x != nil { - return x.DisplayName + return x.TemplateName } return "" } -func (x *Agent_Metadata) GetScript() string { +func (x *Metadata) GetTemplateVersion() string { if x != nil { - return x.Script + return x.TemplateVersion } return "" } -func (x *Agent_Metadata) GetInterval() int64 { +func (x *Metadata) GetWorkspaceOwnerOidcAccessToken() string { if x != nil { - return x.Interval + return x.WorkspaceOwnerOidcAccessToken } - return 0 + return "" } -func (x *Agent_Metadata) GetTimeout() int64 { +func (x *Metadata) GetWorkspaceOwnerSessionToken() string { if x != nil { - return x.Timeout + return x.WorkspaceOwnerSessionToken } - return 0 + return "" } -type Resource_Metadata struct { +// Config represents execution configuration shared by all subsequent requests in the Session +type Config struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` - Sensitive bool `protobuf:"varint,3,opt,name=sensitive,proto3" json:"sensitive,omitempty"` - IsNull bool `protobuf:"varint,4,opt,name=is_null,json=isNull,proto3" json:"is_null,omitempty"` + // template_source_archive is a tar of the template source files + TemplateSourceArchive []byte `protobuf:"bytes,1,opt,name=template_source_archive,json=templateSourceArchive,proto3" json:"template_source_archive,omitempty"` + // state is the provisioner state (if any) + State []byte `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` + ProvisionerLogLevel string `protobuf:"bytes,3,opt,name=provisioner_log_level,json=provisionerLogLevel,proto3" json:"provisioner_log_level,omitempty"` } -func (x *Resource_Metadata) Reset() { - *x = Resource_Metadata{} +func (x *Config) Reset() { + *x = Config{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[17] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *Resource_Metadata) String() string { +func (x *Config) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Resource_Metadata) ProtoMessage() {} +func (*Config) ProtoMessage() {} -func (x *Resource_Metadata) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[17] +func (x *Config) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1509,64 +1482,56 @@ func (x *Resource_Metadata) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Resource_Metadata.ProtoReflect.Descriptor instead. -func (*Resource_Metadata) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{12, 0} -} - -func (x *Resource_Metadata) GetKey() string { - if x != nil { - return x.Key - } - return "" +// Deprecated: Use Config.ProtoReflect.Descriptor instead. +func (*Config) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{14} } -func (x *Resource_Metadata) GetValue() string { +func (x *Config) GetTemplateSourceArchive() []byte { if x != nil { - return x.Value + return x.TemplateSourceArchive } - return "" + return nil } -func (x *Resource_Metadata) GetSensitive() bool { +func (x *Config) GetState() []byte { if x != nil { - return x.Sensitive + return x.State } - return false + return nil } -func (x *Resource_Metadata) GetIsNull() bool { +func (x *Config) GetProvisionerLogLevel() string { if x != nil { - return x.IsNull + return x.ProvisionerLogLevel } - return false + return "" } -type Parse_Request struct { +// ParseRequest consumes source-code to produce inputs. +type ParseRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - - Directory string `protobuf:"bytes,1,opt,name=directory,proto3" json:"directory,omitempty"` } -func (x *Parse_Request) Reset() { - *x = Parse_Request{} +func (x *ParseRequest) Reset() { + *x = ParseRequest{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[18] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *Parse_Request) String() string { +func (x *ParseRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Parse_Request) ProtoMessage() {} +func (*ParseRequest) ProtoMessage() {} -func (x *Parse_Request) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[18] +func (x *ParseRequest) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1577,43 +1542,39 @@ func (x *Parse_Request) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Parse_Request.ProtoReflect.Descriptor instead. -func (*Parse_Request) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{13, 0} +// Deprecated: Use ParseRequest.ProtoReflect.Descriptor instead. +func (*ParseRequest) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{15} } -func (x *Parse_Request) GetDirectory() string { - if x != nil { - return x.Directory - } - return "" -} - -type Parse_Complete struct { +// ParseComplete indicates a request to parse completed. +type ParseComplete struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - TemplateVariables []*TemplateVariable `protobuf:"bytes,1,rep,name=template_variables,json=templateVariables,proto3" json:"template_variables,omitempty"` + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` + TemplateVariables []*TemplateVariable `protobuf:"bytes,2,rep,name=template_variables,json=templateVariables,proto3" json:"template_variables,omitempty"` + Readme []byte `protobuf:"bytes,3,opt,name=readme,proto3" json:"readme,omitempty"` } -func (x *Parse_Complete) Reset() { - *x = Parse_Complete{} +func (x *ParseComplete) Reset() { + *x = ParseComplete{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[19] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *Parse_Complete) String() string { +func (x *ParseComplete) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Parse_Complete) ProtoMessage() {} +func (*ParseComplete) ProtoMessage() {} -func (x *Parse_Complete) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[19] +func (x *ParseComplete) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1624,47 +1585,61 @@ func (x *Parse_Complete) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Parse_Complete.ProtoReflect.Descriptor instead. -func (*Parse_Complete) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{13, 1} +// Deprecated: Use ParseComplete.ProtoReflect.Descriptor instead. +func (*ParseComplete) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{16} } -func (x *Parse_Complete) GetTemplateVariables() []*TemplateVariable { +func (x *ParseComplete) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +func (x *ParseComplete) GetTemplateVariables() []*TemplateVariable { if x != nil { return x.TemplateVariables } return nil } -type Parse_Response struct { +func (x *ParseComplete) GetReadme() []byte { + if x != nil { + return x.Readme + } + return nil +} + +// PlanRequest asks the provisioner to plan what resources & parameters it will create +type PlanRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Types that are assignable to Type: - // - // *Parse_Response_Log - // *Parse_Response_Complete - Type isParse_Response_Type `protobuf_oneof:"type"` + Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` + RichParameterValues []*RichParameterValue `protobuf:"bytes,2,rep,name=rich_parameter_values,json=richParameterValues,proto3" json:"rich_parameter_values,omitempty"` + VariableValues []*VariableValue `protobuf:"bytes,3,rep,name=variable_values,json=variableValues,proto3" json:"variable_values,omitempty"` + GitAuthProviders []*GitAuthProvider `protobuf:"bytes,4,rep,name=git_auth_providers,json=gitAuthProviders,proto3" json:"git_auth_providers,omitempty"` } -func (x *Parse_Response) Reset() { - *x = Parse_Response{} +func (x *PlanRequest) Reset() { + *x = PlanRequest{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[20] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *Parse_Response) String() string { +func (x *PlanRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Parse_Response) ProtoMessage() {} +func (*PlanRequest) ProtoMessage() {} -func (x *Parse_Response) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[20] +func (x *PlanRequest) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1675,83 +1650,68 @@ func (x *Parse_Response) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Parse_Response.ProtoReflect.Descriptor instead. -func (*Parse_Response) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{13, 2} +// Deprecated: Use PlanRequest.ProtoReflect.Descriptor instead. +func (*PlanRequest) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{17} } -func (m *Parse_Response) GetType() isParse_Response_Type { - if m != nil { - return m.Type +func (x *PlanRequest) GetMetadata() *Metadata { + if x != nil { + return x.Metadata } return nil } -func (x *Parse_Response) GetLog() *Log { - if x, ok := x.GetType().(*Parse_Response_Log); ok { - return x.Log +func (x *PlanRequest) GetRichParameterValues() []*RichParameterValue { + if x != nil { + return x.RichParameterValues } return nil } -func (x *Parse_Response) GetComplete() *Parse_Complete { - if x, ok := x.GetType().(*Parse_Response_Complete); ok { - return x.Complete +func (x *PlanRequest) GetVariableValues() []*VariableValue { + if x != nil { + return x.VariableValues } return nil } -type isParse_Response_Type interface { - isParse_Response_Type() -} - -type Parse_Response_Log struct { - Log *Log `protobuf:"bytes,1,opt,name=log,proto3,oneof"` -} - -type Parse_Response_Complete struct { - Complete *Parse_Complete `protobuf:"bytes,2,opt,name=complete,proto3,oneof"` +func (x *PlanRequest) GetGitAuthProviders() []*GitAuthProvider { + if x != nil { + return x.GitAuthProviders + } + return nil } -func (*Parse_Response_Log) isParse_Response_Type() {} - -func (*Parse_Response_Complete) isParse_Response_Type() {} - -type Provision_Metadata struct { +// PlanComplete indicates a request to plan completed. +type PlanComplete struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - CoderUrl string `protobuf:"bytes,1,opt,name=coder_url,json=coderUrl,proto3" json:"coder_url,omitempty"` - WorkspaceTransition WorkspaceTransition `protobuf:"varint,2,opt,name=workspace_transition,json=workspaceTransition,proto3,enum=provisioner.WorkspaceTransition" json:"workspace_transition,omitempty"` - WorkspaceName string `protobuf:"bytes,3,opt,name=workspace_name,json=workspaceName,proto3" json:"workspace_name,omitempty"` - WorkspaceOwner string `protobuf:"bytes,4,opt,name=workspace_owner,json=workspaceOwner,proto3" json:"workspace_owner,omitempty"` - WorkspaceId string `protobuf:"bytes,5,opt,name=workspace_id,json=workspaceId,proto3" json:"workspace_id,omitempty"` - WorkspaceOwnerId string `protobuf:"bytes,6,opt,name=workspace_owner_id,json=workspaceOwnerId,proto3" json:"workspace_owner_id,omitempty"` - WorkspaceOwnerEmail string `protobuf:"bytes,7,opt,name=workspace_owner_email,json=workspaceOwnerEmail,proto3" json:"workspace_owner_email,omitempty"` - TemplateName string `protobuf:"bytes,8,opt,name=template_name,json=templateName,proto3" json:"template_name,omitempty"` - TemplateVersion string `protobuf:"bytes,9,opt,name=template_version,json=templateVersion,proto3" json:"template_version,omitempty"` - WorkspaceOwnerOidcAccessToken string `protobuf:"bytes,10,opt,name=workspace_owner_oidc_access_token,json=workspaceOwnerOidcAccessToken,proto3" json:"workspace_owner_oidc_access_token,omitempty"` - WorkspaceOwnerSessionToken string `protobuf:"bytes,11,opt,name=workspace_owner_session_token,json=workspaceOwnerSessionToken,proto3" json:"workspace_owner_session_token,omitempty"` + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` + Resources []*Resource `protobuf:"bytes,2,rep,name=resources,proto3" json:"resources,omitempty"` + Parameters []*RichParameter `protobuf:"bytes,3,rep,name=parameters,proto3" json:"parameters,omitempty"` + GitAuthProviders []string `protobuf:"bytes,4,rep,name=git_auth_providers,json=gitAuthProviders,proto3" json:"git_auth_providers,omitempty"` } -func (x *Provision_Metadata) Reset() { - *x = Provision_Metadata{} +func (x *PlanComplete) Reset() { + *x = PlanComplete{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[21] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *Provision_Metadata) String() string { +func (x *PlanComplete) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Provision_Metadata) ProtoMessage() {} +func (*PlanComplete) ProtoMessage() {} -func (x *Provision_Metadata) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[21] +func (x *PlanComplete) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1762,118 +1722,118 @@ func (x *Provision_Metadata) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Provision_Metadata.ProtoReflect.Descriptor instead. -func (*Provision_Metadata) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{14, 0} +// Deprecated: Use PlanComplete.ProtoReflect.Descriptor instead. +func (*PlanComplete) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{18} } -func (x *Provision_Metadata) GetCoderUrl() string { +func (x *PlanComplete) GetError() string { if x != nil { - return x.CoderUrl + return x.Error } return "" } -func (x *Provision_Metadata) GetWorkspaceTransition() WorkspaceTransition { +func (x *PlanComplete) GetResources() []*Resource { if x != nil { - return x.WorkspaceTransition + return x.Resources } - return WorkspaceTransition_START + return nil } -func (x *Provision_Metadata) GetWorkspaceName() string { +func (x *PlanComplete) GetParameters() []*RichParameter { if x != nil { - return x.WorkspaceName + return x.Parameters } - return "" + return nil } -func (x *Provision_Metadata) GetWorkspaceOwner() string { +func (x *PlanComplete) GetGitAuthProviders() []string { if x != nil { - return x.WorkspaceOwner + return x.GitAuthProviders } - return "" + return nil } -func (x *Provision_Metadata) GetWorkspaceId() string { - if x != nil { - return x.WorkspaceId - } - return "" -} +// 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 { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (x *Provision_Metadata) GetWorkspaceOwnerId() string { - if x != nil { - return x.WorkspaceOwnerId - } - return "" + Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` } -func (x *Provision_Metadata) GetWorkspaceOwnerEmail() string { - if x != nil { - return x.WorkspaceOwnerEmail +func (x *ApplyRequest) Reset() { + *x = ApplyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } - return "" } -func (x *Provision_Metadata) GetTemplateName() string { - if x != nil { - return x.TemplateName - } - return "" +func (x *ApplyRequest) String() string { + return protoimpl.X.MessageStringOf(x) } -func (x *Provision_Metadata) GetTemplateVersion() string { - if x != nil { - return x.TemplateVersion +func (*ApplyRequest) ProtoMessage() {} + +func (x *ApplyRequest) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms } - return "" + return mi.MessageOf(x) } -func (x *Provision_Metadata) GetWorkspaceOwnerOidcAccessToken() string { - if x != nil { - return x.WorkspaceOwnerOidcAccessToken - } - return "" +// Deprecated: Use ApplyRequest.ProtoReflect.Descriptor instead. +func (*ApplyRequest) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{19} } -func (x *Provision_Metadata) GetWorkspaceOwnerSessionToken() string { +func (x *ApplyRequest) GetMetadata() *Metadata { if x != nil { - return x.WorkspaceOwnerSessionToken + return x.Metadata } - return "" + return nil } -// Config represents execution configuration shared by both Plan and -// Apply commands. -type Provision_Config struct { +// ApplyComplete indicates a request to apply completed. +type ApplyComplete struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Directory string `protobuf:"bytes,1,opt,name=directory,proto3" json:"directory,omitempty"` - State []byte `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` - Metadata *Provision_Metadata `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"` - ProvisionerLogLevel string `protobuf:"bytes,4,opt,name=provisioner_log_level,json=provisionerLogLevel,proto3" json:"provisioner_log_level,omitempty"` + State []byte `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + Resources []*Resource `protobuf:"bytes,3,rep,name=resources,proto3" json:"resources,omitempty"` + Parameters []*RichParameter `protobuf:"bytes,4,rep,name=parameters,proto3" json:"parameters,omitempty"` + GitAuthProviders []string `protobuf:"bytes,5,rep,name=git_auth_providers,json=gitAuthProviders,proto3" json:"git_auth_providers,omitempty"` } -func (x *Provision_Config) Reset() { - *x = Provision_Config{} +func (x *ApplyComplete) Reset() { + *x = ApplyComplete{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[22] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *Provision_Config) String() string { +func (x *ApplyComplete) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Provision_Config) ProtoMessage() {} +func (*ApplyComplete) ProtoMessage() {} -func (x *Provision_Config) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[22] +func (x *ApplyComplete) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1884,67 +1844,70 @@ func (x *Provision_Config) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Provision_Config.ProtoReflect.Descriptor instead. -func (*Provision_Config) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{14, 1} +// Deprecated: Use ApplyComplete.ProtoReflect.Descriptor instead. +func (*ApplyComplete) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{20} } -func (x *Provision_Config) GetDirectory() string { +func (x *ApplyComplete) GetState() []byte { if x != nil { - return x.Directory + return x.State + } + return nil +} + +func (x *ApplyComplete) GetError() string { + if x != nil { + return x.Error } return "" } -func (x *Provision_Config) GetState() []byte { +func (x *ApplyComplete) GetResources() []*Resource { if x != nil { - return x.State + return x.Resources } return nil } -func (x *Provision_Config) GetMetadata() *Provision_Metadata { +func (x *ApplyComplete) GetParameters() []*RichParameter { if x != nil { - return x.Metadata + return x.Parameters } return nil } -func (x *Provision_Config) GetProvisionerLogLevel() string { +func (x *ApplyComplete) GetGitAuthProviders() []string { if x != nil { - return x.ProvisionerLogLevel + return x.GitAuthProviders } - return "" + return nil } -type Provision_Plan struct { +// CancelRequest requests that the previous request be canceled gracefully. +type CancelRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - - Config *Provision_Config `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - RichParameterValues []*RichParameterValue `protobuf:"bytes,3,rep,name=rich_parameter_values,json=richParameterValues,proto3" json:"rich_parameter_values,omitempty"` - VariableValues []*VariableValue `protobuf:"bytes,4,rep,name=variable_values,json=variableValues,proto3" json:"variable_values,omitempty"` - GitAuthProviders []*GitAuthProvider `protobuf:"bytes,5,rep,name=git_auth_providers,json=gitAuthProviders,proto3" json:"git_auth_providers,omitempty"` } -func (x *Provision_Plan) Reset() { - *x = Provision_Plan{} +func (x *CancelRequest) Reset() { + *x = CancelRequest{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[23] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *Provision_Plan) String() string { +func (x *CancelRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Provision_Plan) ProtoMessage() {} +func (*CancelRequest) ProtoMessage() {} -func (x *Provision_Plan) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[23] +func (x *CancelRequest) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1955,65 +1918,43 @@ func (x *Provision_Plan) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Provision_Plan.ProtoReflect.Descriptor instead. -func (*Provision_Plan) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{14, 2} -} - -func (x *Provision_Plan) GetConfig() *Provision_Config { - if x != nil { - return x.Config - } - return nil -} - -func (x *Provision_Plan) GetRichParameterValues() []*RichParameterValue { - if x != nil { - return x.RichParameterValues - } - return nil -} - -func (x *Provision_Plan) GetVariableValues() []*VariableValue { - if x != nil { - return x.VariableValues - } - return nil -} - -func (x *Provision_Plan) GetGitAuthProviders() []*GitAuthProvider { - if x != nil { - return x.GitAuthProviders - } - return nil +// Deprecated: Use CancelRequest.ProtoReflect.Descriptor instead. +func (*CancelRequest) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{21} } -type Provision_Apply struct { +type Request struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Config *Provision_Config `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - Plan []byte `protobuf:"bytes,2,opt,name=plan,proto3" json:"plan,omitempty"` + // Types that are assignable to Type: + // + // *Request_Config + // *Request_Parse + // *Request_Plan + // *Request_Apply + // *Request_Cancel + Type isRequest_Type `protobuf_oneof:"type"` } -func (x *Provision_Apply) Reset() { - *x = Provision_Apply{} +func (x *Request) Reset() { + *x = Request{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[24] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *Provision_Apply) String() string { +func (x *Request) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Provision_Apply) ProtoMessage() {} +func (*Request) ProtoMessage() {} -func (x *Provision_Apply) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[24] +func (x *Request) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2024,93 +1965,118 @@ func (x *Provision_Apply) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Provision_Apply.ProtoReflect.Descriptor instead. -func (*Provision_Apply) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{14, 3} +// Deprecated: Use Request.ProtoReflect.Descriptor instead. +func (*Request) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{22} } -func (x *Provision_Apply) GetConfig() *Provision_Config { - if x != nil { +func (m *Request) GetType() isRequest_Type { + if m != nil { + return m.Type + } + return nil +} + +func (x *Request) GetConfig() *Config { + if x, ok := x.GetType().(*Request_Config); ok { return x.Config } return nil } -func (x *Provision_Apply) GetPlan() []byte { - if x != nil { +func (x *Request) GetParse() *ParseRequest { + if x, ok := x.GetType().(*Request_Parse); ok { + return x.Parse + } + return nil +} + +func (x *Request) GetPlan() *PlanRequest { + if x, ok := x.GetType().(*Request_Plan); ok { return x.Plan } return nil } -type Provision_Cancel struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields +func (x *Request) GetApply() *ApplyRequest { + if x, ok := x.GetType().(*Request_Apply); ok { + return x.Apply + } + return nil } -func (x *Provision_Cancel) Reset() { - *x = Provision_Cancel{} - if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) +func (x *Request) GetCancel() *CancelRequest { + if x, ok := x.GetType().(*Request_Cancel); ok { + return x.Cancel } + return nil } -func (x *Provision_Cancel) String() string { - return protoimpl.X.MessageStringOf(x) +type isRequest_Type interface { + isRequest_Type() +} + +type Request_Config struct { + Config *Config `protobuf:"bytes,1,opt,name=config,proto3,oneof"` } -func (*Provision_Cancel) ProtoMessage() {} +type Request_Parse struct { + Parse *ParseRequest `protobuf:"bytes,2,opt,name=parse,proto3,oneof"` +} -func (x *Provision_Cancel) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[25] - 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) +type Request_Plan struct { + Plan *PlanRequest `protobuf:"bytes,3,opt,name=plan,proto3,oneof"` +} + +type Request_Apply struct { + Apply *ApplyRequest `protobuf:"bytes,4,opt,name=apply,proto3,oneof"` } -// Deprecated: Use Provision_Cancel.ProtoReflect.Descriptor instead. -func (*Provision_Cancel) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{14, 4} +type Request_Cancel struct { + Cancel *CancelRequest `protobuf:"bytes,5,opt,name=cancel,proto3,oneof"` } -type Provision_Request struct { +func (*Request_Config) isRequest_Type() {} + +func (*Request_Parse) isRequest_Type() {} + +func (*Request_Plan) isRequest_Type() {} + +func (*Request_Apply) isRequest_Type() {} + +func (*Request_Cancel) isRequest_Type() {} + +type Response struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Types that are assignable to Type: // - // *Provision_Request_Plan - // *Provision_Request_Apply - // *Provision_Request_Cancel - Type isProvision_Request_Type `protobuf_oneof:"type"` + // *Response_Log + // *Response_Parse + // *Response_Plan + // *Response_Apply + Type isResponse_Type `protobuf_oneof:"type"` } -func (x *Provision_Request) Reset() { - *x = Provision_Request{} +func (x *Response) Reset() { + *x = Response{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[26] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *Provision_Request) String() string { +func (x *Response) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Provision_Request) ProtoMessage() {} +func (*Response) ProtoMessage() {} -func (x *Provision_Request) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[26] +func (x *Response) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2121,91 +2087,103 @@ func (x *Provision_Request) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Provision_Request.ProtoReflect.Descriptor instead. -func (*Provision_Request) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{14, 5} +// Deprecated: Use Response.ProtoReflect.Descriptor instead. +func (*Response) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{23} } -func (m *Provision_Request) GetType() isProvision_Request_Type { +func (m *Response) GetType() isResponse_Type { if m != nil { return m.Type } return nil } -func (x *Provision_Request) GetPlan() *Provision_Plan { - if x, ok := x.GetType().(*Provision_Request_Plan); ok { - return x.Plan +func (x *Response) GetLog() *Log { + if x, ok := x.GetType().(*Response_Log); ok { + return x.Log } return nil } -func (x *Provision_Request) GetApply() *Provision_Apply { - if x, ok := x.GetType().(*Provision_Request_Apply); ok { - return x.Apply +func (x *Response) GetParse() *ParseComplete { + if x, ok := x.GetType().(*Response_Parse); ok { + return x.Parse } return nil } -func (x *Provision_Request) GetCancel() *Provision_Cancel { - if x, ok := x.GetType().(*Provision_Request_Cancel); ok { - return x.Cancel +func (x *Response) GetPlan() *PlanComplete { + if x, ok := x.GetType().(*Response_Plan); ok { + return x.Plan + } + return nil +} + +func (x *Response) GetApply() *ApplyComplete { + if x, ok := x.GetType().(*Response_Apply); ok { + return x.Apply } return nil } -type isProvision_Request_Type interface { - isProvision_Request_Type() +type isResponse_Type interface { + isResponse_Type() +} + +type Response_Log struct { + Log *Log `protobuf:"bytes,1,opt,name=log,proto3,oneof"` } -type Provision_Request_Plan struct { - Plan *Provision_Plan `protobuf:"bytes,1,opt,name=plan,proto3,oneof"` +type Response_Parse struct { + Parse *ParseComplete `protobuf:"bytes,2,opt,name=parse,proto3,oneof"` } -type Provision_Request_Apply struct { - Apply *Provision_Apply `protobuf:"bytes,2,opt,name=apply,proto3,oneof"` +type Response_Plan struct { + Plan *PlanComplete `protobuf:"bytes,3,opt,name=plan,proto3,oneof"` } -type Provision_Request_Cancel struct { - Cancel *Provision_Cancel `protobuf:"bytes,3,opt,name=cancel,proto3,oneof"` +type Response_Apply struct { + Apply *ApplyComplete `protobuf:"bytes,4,opt,name=apply,proto3,oneof"` } -func (*Provision_Request_Plan) isProvision_Request_Type() {} +func (*Response_Log) isResponse_Type() {} -func (*Provision_Request_Apply) isProvision_Request_Type() {} +func (*Response_Parse) isResponse_Type() {} -func (*Provision_Request_Cancel) isProvision_Request_Type() {} +func (*Response_Plan) isResponse_Type() {} -type Provision_Complete struct { +func (*Response_Apply) isResponse_Type() {} + +type Agent_Metadata struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - State []byte `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` - Resources []*Resource `protobuf:"bytes,3,rep,name=resources,proto3" json:"resources,omitempty"` - Parameters []*RichParameter `protobuf:"bytes,4,rep,name=parameters,proto3" json:"parameters,omitempty"` - GitAuthProviders []string `protobuf:"bytes,5,rep,name=git_auth_providers,json=gitAuthProviders,proto3" json:"git_auth_providers,omitempty"` - Plan []byte `protobuf:"bytes,6,opt,name=plan,proto3" json:"plan,omitempty"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` + Script string `protobuf:"bytes,3,opt,name=script,proto3" json:"script,omitempty"` + Interval int64 `protobuf:"varint,4,opt,name=interval,proto3" json:"interval,omitempty"` + Timeout int64 `protobuf:"varint,5,opt,name=timeout,proto3" json:"timeout,omitempty"` } -func (x *Provision_Complete) Reset() { - *x = Provision_Complete{} +func (x *Agent_Metadata) Reset() { + *x = Agent_Metadata{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[27] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *Provision_Complete) String() string { +func (x *Agent_Metadata) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Provision_Complete) ProtoMessage() {} +func (*Agent_Metadata) ProtoMessage() {} -func (x *Provision_Complete) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[27] +func (x *Agent_Metadata) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2216,82 +2194,74 @@ func (x *Provision_Complete) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Provision_Complete.ProtoReflect.Descriptor instead. -func (*Provision_Complete) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{14, 6} -} - -func (x *Provision_Complete) GetState() []byte { - if x != nil { - return x.State - } - return nil +// Deprecated: Use Agent_Metadata.ProtoReflect.Descriptor instead. +func (*Agent_Metadata) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{9, 0} } -func (x *Provision_Complete) GetError() string { +func (x *Agent_Metadata) GetKey() string { if x != nil { - return x.Error + return x.Key } return "" } -func (x *Provision_Complete) GetResources() []*Resource { +func (x *Agent_Metadata) GetDisplayName() string { if x != nil { - return x.Resources + return x.DisplayName } - return nil + return "" } -func (x *Provision_Complete) GetParameters() []*RichParameter { +func (x *Agent_Metadata) GetScript() string { if x != nil { - return x.Parameters + return x.Script } - return nil + return "" } -func (x *Provision_Complete) GetGitAuthProviders() []string { +func (x *Agent_Metadata) GetInterval() int64 { if x != nil { - return x.GitAuthProviders + return x.Interval } - return nil + return 0 } -func (x *Provision_Complete) GetPlan() []byte { +func (x *Agent_Metadata) GetTimeout() int64 { if x != nil { - return x.Plan + return x.Timeout } - return nil + return 0 } -type Provision_Response struct { +type Resource_Metadata struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Types that are assignable to Type: - // - // *Provision_Response_Log - // *Provision_Response_Complete - Type isProvision_Response_Type `protobuf_oneof:"type"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + Sensitive bool `protobuf:"varint,3,opt,name=sensitive,proto3" json:"sensitive,omitempty"` + IsNull bool `protobuf:"varint,4,opt,name=is_null,json=isNull,proto3" json:"is_null,omitempty"` } -func (x *Provision_Response) Reset() { - *x = Provision_Response{} +func (x *Resource_Metadata) Reset() { + *x = Resource_Metadata{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[28] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *Provision_Response) String() string { +func (x *Resource_Metadata) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Provision_Response) ProtoMessage() {} +func (*Resource_Metadata) ProtoMessage() {} -func (x *Provision_Response) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[28] +func (x *Resource_Metadata) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2302,48 +2272,39 @@ func (x *Provision_Response) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Provision_Response.ProtoReflect.Descriptor instead. -func (*Provision_Response) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{14, 7} +// Deprecated: Use Resource_Metadata.ProtoReflect.Descriptor instead. +func (*Resource_Metadata) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{12, 0} } -func (m *Provision_Response) GetType() isProvision_Response_Type { - if m != nil { - return m.Type +func (x *Resource_Metadata) GetKey() string { + if x != nil { + return x.Key } - return nil + return "" } -func (x *Provision_Response) GetLog() *Log { - if x, ok := x.GetType().(*Provision_Response_Log); ok { - return x.Log +func (x *Resource_Metadata) GetValue() string { + if x != nil { + return x.Value } - return nil + return "" } -func (x *Provision_Response) GetComplete() *Provision_Complete { - if x, ok := x.GetType().(*Provision_Response_Complete); ok { - return x.Complete +func (x *Resource_Metadata) GetSensitive() bool { + if x != nil { + return x.Sensitive } - return nil -} - -type isProvision_Response_Type interface { - isProvision_Response_Type() -} - -type Provision_Response_Log struct { - Log *Log `protobuf:"bytes,1,opt,name=log,proto3,oneof"` + return false } -type Provision_Response_Complete struct { - Complete *Provision_Complete `protobuf:"bytes,2,opt,name=complete,proto3,oneof"` +func (x *Resource_Metadata) GetIsNull() bool { + if x != nil { + return x.IsNull + } + return false } -func (*Provision_Response_Log) isProvision_Response_Type() {} - -func (*Provision_Response_Complete) isProvision_Response_Type() {} - var File_provisionersdk_proto_provisioner_proto protoreflect.FileDescriptor var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ @@ -2543,154 +2504,161 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x6e, 0x75, 0x6c, 0x6c, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x4e, 0x75, 0x6c, 0x6c, 0x22, 0x85, 0x02, - 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x1a, 0x27, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, - 0x1a, 0x5e, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x4c, 0x0a, 0x12, - 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, - 0x65, 0x73, 0x18, 0x01, 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, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, - 0x1a, 0x73, 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, 0x39, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, - 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x91, 0x0d, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x1a, 0xae, 0x04, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x53, 0x0a, - 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x77, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, - 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, - 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, - 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x65, 0x6d, 0x70, 0x6c, - 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, - 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a, 0x21, 0x77, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6f, 0x69, 0x64, 0x63, 0x5f, - 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, - 0x65, 0x72, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x12, 0x41, 0x0a, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, - 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x1a, 0xad, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x14, 0x0a, - 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x12, 0x32, 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x5f, - 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x13, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x4c, - 0x65, 0x76, 0x65, 0x6c, 0x1a, 0xa9, 0x02, 0x0a, 0x04, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x35, 0x0a, - 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x53, 0x0a, 0x15, 0x72, 0x69, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, - 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0b, 0x32, 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, 0x13, 0x72, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x76, 0x61, 0x72, - 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x4e, 0x75, 0x6c, 0x6c, 0x22, 0xae, 0x04, + 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, + 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, + 0x6f, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x53, 0x0a, 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, + 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, + 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, + 0x2c, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x77, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x32, 0x0a, + 0x15, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, + 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, + 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, + 0x74, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x48, 0x0a, 0x21, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1d, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x4f, 0x69, 0x64, 0x63, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x41, 0x0a, 0x1d, 0x77, + 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x1a, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, + 0x65, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x8a, + 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x17, 0x74, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x72, 0x63, + 0x68, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x15, 0x74, 0x65, 0x6d, 0x70, + 0x6c, 0x61, 0x74, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x0e, 0x0a, 0x0c, 0x50, + 0x61, 0x72, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8b, 0x01, 0x0a, 0x0d, + 0x50, 0x61, 0x72, 0x73, 0x65, 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, 0x4c, 0x0a, 0x12, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, + 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x02, 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, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x22, 0xa6, 0x02, 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, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x53, 0x0a, 0x15, + 0x72, 0x69, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 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, 0x13, 0x72, 0x69, + 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x73, 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, 0x12, 0x4a, 0x0a, 0x12, 0x67, 0x69, 0x74, 0x5f, 0x61, 0x75, + 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x2e, 0x47, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x52, 0x10, 0x67, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x73, 0x22, 0xc3, 0x01, 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, 0x2c, 0x0a, 0x12, 0x67, 0x69, + 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x67, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 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, 0xda, 0x01, 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, 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, 0x12, 0x4a, - 0x0a, 0x12, 0x67, 0x69, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x47, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x10, 0x67, 0x69, 0x74, 0x41, 0x75, 0x74, - 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, - 0x1a, 0x52, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x35, 0x0a, 0x06, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, - 0x70, 0x6c, 0x61, 0x6e, 0x1a, 0x08, 0x0a, 0x06, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x1a, 0xb3, - 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x04, 0x70, 0x6c, - 0x61, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x34, 0x0a, - 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70, - 0x70, 0x6c, 0x79, 0x12, 0x37, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, - 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x61, 0x6e, 0x63, - 0x65, 0x6c, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x06, 0x0a, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x1a, 0xe9, 0x01, 0x0a, 0x08, 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, 0x2c, - 0x0a, 0x12, 0x67, 0x69, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x67, 0x69, 0x74, 0x41, - 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, - 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, - 0x1a, 0x77, 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, 0x3d, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, - 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, - 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 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, 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, - 0x32, 0xa3, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x12, 0x42, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x30, 0x01, 0x12, 0x50, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 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, + 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, 0x2c, 0x0a, 0x12, 0x67, 0x69, + 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, + 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x67, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 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, 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, 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, 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, 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 ( @@ -2706,7 +2674,7 @@ func file_provisionersdk_proto_provisioner_proto_rawDescGZIP() []byte { } var file_provisionersdk_proto_provisioner_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_provisionersdk_proto_provisioner_proto_msgTypes = make([]protoimpl.MessageInfo, 29) +var file_provisionersdk_proto_provisioner_proto_msgTypes = make([]protoimpl.MessageInfo, 27) var file_provisionersdk_proto_provisioner_proto_goTypes = []interface{}{ (LogLevel)(0), // 0: provisioner.LogLevel (AppSharingLevel)(0), // 1: provisioner.AppSharingLevel @@ -2724,59 +2692,58 @@ var file_provisionersdk_proto_provisioner_proto_goTypes = []interface{}{ (*App)(nil), // 13: provisioner.App (*Healthcheck)(nil), // 14: provisioner.Healthcheck (*Resource)(nil), // 15: provisioner.Resource - (*Parse)(nil), // 16: provisioner.Parse - (*Provision)(nil), // 17: provisioner.Provision - (*Agent_Metadata)(nil), // 18: provisioner.Agent.Metadata - nil, // 19: provisioner.Agent.EnvEntry - (*Resource_Metadata)(nil), // 20: provisioner.Resource.Metadata - (*Parse_Request)(nil), // 21: provisioner.Parse.Request - (*Parse_Complete)(nil), // 22: provisioner.Parse.Complete - (*Parse_Response)(nil), // 23: provisioner.Parse.Response - (*Provision_Metadata)(nil), // 24: provisioner.Provision.Metadata - (*Provision_Config)(nil), // 25: provisioner.Provision.Config - (*Provision_Plan)(nil), // 26: provisioner.Provision.Plan - (*Provision_Apply)(nil), // 27: provisioner.Provision.Apply - (*Provision_Cancel)(nil), // 28: provisioner.Provision.Cancel - (*Provision_Request)(nil), // 29: provisioner.Provision.Request - (*Provision_Complete)(nil), // 30: provisioner.Provision.Complete - (*Provision_Response)(nil), // 31: provisioner.Provision.Response + (*Metadata)(nil), // 16: provisioner.Metadata + (*Config)(nil), // 17: provisioner.Config + (*ParseRequest)(nil), // 18: provisioner.ParseRequest + (*ParseComplete)(nil), // 19: provisioner.ParseComplete + (*PlanRequest)(nil), // 20: provisioner.PlanRequest + (*PlanComplete)(nil), // 21: provisioner.PlanComplete + (*ApplyRequest)(nil), // 22: provisioner.ApplyRequest + (*ApplyComplete)(nil), // 23: provisioner.ApplyComplete + (*CancelRequest)(nil), // 24: provisioner.CancelRequest + (*Request)(nil), // 25: provisioner.Request + (*Response)(nil), // 26: provisioner.Response + (*Agent_Metadata)(nil), // 27: provisioner.Agent.Metadata + nil, // 28: provisioner.Agent.EnvEntry + (*Resource_Metadata)(nil), // 29: provisioner.Resource.Metadata } var file_provisionersdk_proto_provisioner_proto_depIdxs = []int32{ 5, // 0: provisioner.RichParameter.options:type_name -> provisioner.RichParameterOption 0, // 1: provisioner.Log.level:type_name -> provisioner.LogLevel - 19, // 2: provisioner.Agent.env:type_name -> provisioner.Agent.EnvEntry + 28, // 2: provisioner.Agent.env:type_name -> provisioner.Agent.EnvEntry 13, // 3: provisioner.Agent.apps:type_name -> provisioner.App - 18, // 4: provisioner.Agent.metadata:type_name -> provisioner.Agent.Metadata + 27, // 4: provisioner.Agent.metadata:type_name -> provisioner.Agent.Metadata 14, // 5: provisioner.App.healthcheck:type_name -> provisioner.Healthcheck 1, // 6: provisioner.App.sharing_level:type_name -> provisioner.AppSharingLevel 12, // 7: provisioner.Resource.agents:type_name -> provisioner.Agent - 20, // 8: provisioner.Resource.metadata:type_name -> provisioner.Resource.Metadata - 4, // 9: provisioner.Parse.Complete.template_variables:type_name -> provisioner.TemplateVariable - 9, // 10: provisioner.Parse.Response.log:type_name -> provisioner.Log - 22, // 11: provisioner.Parse.Response.complete:type_name -> provisioner.Parse.Complete - 2, // 12: provisioner.Provision.Metadata.workspace_transition:type_name -> provisioner.WorkspaceTransition - 24, // 13: provisioner.Provision.Config.metadata:type_name -> provisioner.Provision.Metadata - 25, // 14: provisioner.Provision.Plan.config:type_name -> provisioner.Provision.Config - 7, // 15: provisioner.Provision.Plan.rich_parameter_values:type_name -> provisioner.RichParameterValue - 8, // 16: provisioner.Provision.Plan.variable_values:type_name -> provisioner.VariableValue - 11, // 17: provisioner.Provision.Plan.git_auth_providers:type_name -> provisioner.GitAuthProvider - 25, // 18: provisioner.Provision.Apply.config:type_name -> provisioner.Provision.Config - 26, // 19: provisioner.Provision.Request.plan:type_name -> provisioner.Provision.Plan - 27, // 20: provisioner.Provision.Request.apply:type_name -> provisioner.Provision.Apply - 28, // 21: provisioner.Provision.Request.cancel:type_name -> provisioner.Provision.Cancel - 15, // 22: provisioner.Provision.Complete.resources:type_name -> provisioner.Resource - 6, // 23: provisioner.Provision.Complete.parameters:type_name -> provisioner.RichParameter - 9, // 24: provisioner.Provision.Response.log:type_name -> provisioner.Log - 30, // 25: provisioner.Provision.Response.complete:type_name -> provisioner.Provision.Complete - 21, // 26: provisioner.Provisioner.Parse:input_type -> provisioner.Parse.Request - 29, // 27: provisioner.Provisioner.Provision:input_type -> provisioner.Provision.Request - 23, // 28: provisioner.Provisioner.Parse:output_type -> provisioner.Parse.Response - 31, // 29: provisioner.Provisioner.Provision:output_type -> provisioner.Provision.Response - 28, // [28:30] is the sub-list for method output_type - 26, // [26:28] is the sub-list for method input_type - 26, // [26:26] is the sub-list for extension type_name - 26, // [26:26] is the sub-list for extension extendee - 0, // [0:26] is the sub-list for field type_name + 29, // 8: provisioner.Resource.metadata:type_name -> provisioner.Resource.Metadata + 2, // 9: provisioner.Metadata.workspace_transition:type_name -> provisioner.WorkspaceTransition + 4, // 10: provisioner.ParseComplete.template_variables:type_name -> provisioner.TemplateVariable + 16, // 11: provisioner.PlanRequest.metadata:type_name -> provisioner.Metadata + 7, // 12: provisioner.PlanRequest.rich_parameter_values:type_name -> provisioner.RichParameterValue + 8, // 13: provisioner.PlanRequest.variable_values:type_name -> provisioner.VariableValue + 11, // 14: provisioner.PlanRequest.git_auth_providers:type_name -> provisioner.GitAuthProvider + 15, // 15: provisioner.PlanComplete.resources:type_name -> provisioner.Resource + 6, // 16: provisioner.PlanComplete.parameters:type_name -> provisioner.RichParameter + 16, // 17: provisioner.ApplyRequest.metadata:type_name -> provisioner.Metadata + 15, // 18: provisioner.ApplyComplete.resources:type_name -> provisioner.Resource + 6, // 19: provisioner.ApplyComplete.parameters:type_name -> provisioner.RichParameter + 17, // 20: provisioner.Request.config:type_name -> provisioner.Config + 18, // 21: provisioner.Request.parse:type_name -> provisioner.ParseRequest + 20, // 22: provisioner.Request.plan:type_name -> provisioner.PlanRequest + 22, // 23: provisioner.Request.apply:type_name -> provisioner.ApplyRequest + 24, // 24: provisioner.Request.cancel:type_name -> provisioner.CancelRequest + 9, // 25: provisioner.Response.log:type_name -> provisioner.Log + 19, // 26: provisioner.Response.parse:type_name -> provisioner.ParseComplete + 21, // 27: provisioner.Response.plan:type_name -> provisioner.PlanComplete + 23, // 28: provisioner.Response.apply:type_name -> provisioner.ApplyComplete + 25, // 29: provisioner.Provisioner.Session:input_type -> provisioner.Request + 26, // 30: provisioner.Provisioner.Session:output_type -> provisioner.Response + 30, // [30:31] is the sub-list for method output_type + 29, // [29:30] is the sub-list for method input_type + 29, // [29:29] is the sub-list for extension type_name + 29, // [29:29] is the sub-list for extension extendee + 0, // [0:29] is the sub-list for field type_name } func init() { file_provisionersdk_proto_provisioner_proto_init() } @@ -2942,7 +2909,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } file_provisionersdk_proto_provisioner_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Parse); i { + switch v := v.(*Metadata); i { case 0: return &v.state case 1: @@ -2954,7 +2921,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } file_provisionersdk_proto_provisioner_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Provision); i { + switch v := v.(*Config); i { case 0: return &v.state case 1: @@ -2966,7 +2933,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } file_provisionersdk_proto_provisioner_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Agent_Metadata); i { + switch v := v.(*ParseRequest); i { case 0: return &v.state case 1: @@ -2977,8 +2944,8 @@ func file_provisionersdk_proto_provisioner_proto_init() { return nil } } - file_provisionersdk_proto_provisioner_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Resource_Metadata); i { + file_provisionersdk_proto_provisioner_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ParseComplete); i { case 0: return &v.state case 1: @@ -2989,8 +2956,8 @@ func file_provisionersdk_proto_provisioner_proto_init() { return nil } } - file_provisionersdk_proto_provisioner_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Parse_Request); i { + file_provisionersdk_proto_provisioner_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PlanRequest); i { case 0: return &v.state case 1: @@ -3001,8 +2968,8 @@ func file_provisionersdk_proto_provisioner_proto_init() { return nil } } - file_provisionersdk_proto_provisioner_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Parse_Complete); i { + file_provisionersdk_proto_provisioner_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PlanComplete); i { case 0: return &v.state case 1: @@ -3013,8 +2980,8 @@ func file_provisionersdk_proto_provisioner_proto_init() { return nil } } - file_provisionersdk_proto_provisioner_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Parse_Response); i { + file_provisionersdk_proto_provisioner_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyRequest); i { case 0: return &v.state case 1: @@ -3025,8 +2992,8 @@ func file_provisionersdk_proto_provisioner_proto_init() { return nil } } - file_provisionersdk_proto_provisioner_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Provision_Metadata); i { + file_provisionersdk_proto_provisioner_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyComplete); i { case 0: return &v.state case 1: @@ -3037,8 +3004,8 @@ func file_provisionersdk_proto_provisioner_proto_init() { return nil } } - file_provisionersdk_proto_provisioner_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Provision_Config); i { + file_provisionersdk_proto_provisioner_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CancelRequest); i { case 0: return &v.state case 1: @@ -3049,8 +3016,8 @@ func file_provisionersdk_proto_provisioner_proto_init() { return nil } } - file_provisionersdk_proto_provisioner_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Provision_Plan); i { + file_provisionersdk_proto_provisioner_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Request); i { case 0: return &v.state case 1: @@ -3061,8 +3028,8 @@ func file_provisionersdk_proto_provisioner_proto_init() { return nil } } - file_provisionersdk_proto_provisioner_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Provision_Apply); i { + file_provisionersdk_proto_provisioner_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Response); i { case 0: return &v.state case 1: @@ -3073,8 +3040,8 @@ func file_provisionersdk_proto_provisioner_proto_init() { return nil } } - file_provisionersdk_proto_provisioner_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Provision_Cancel); i { + file_provisionersdk_proto_provisioner_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Agent_Metadata); i { case 0: return &v.state case 1: @@ -3086,31 +3053,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } file_provisionersdk_proto_provisioner_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Provision_Request); 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[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Provision_Complete); 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[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Provision_Response); i { + switch v := v.(*Resource_Metadata); i { case 0: return &v.state case 1: @@ -3127,18 +3070,18 @@ func file_provisionersdk_proto_provisioner_proto_init() { (*Agent_Token)(nil), (*Agent_InstanceId)(nil), } - file_provisionersdk_proto_provisioner_proto_msgTypes[20].OneofWrappers = []interface{}{ - (*Parse_Response_Log)(nil), - (*Parse_Response_Complete)(nil), - } - file_provisionersdk_proto_provisioner_proto_msgTypes[26].OneofWrappers = []interface{}{ - (*Provision_Request_Plan)(nil), - (*Provision_Request_Apply)(nil), - (*Provision_Request_Cancel)(nil), + file_provisionersdk_proto_provisioner_proto_msgTypes[22].OneofWrappers = []interface{}{ + (*Request_Config)(nil), + (*Request_Parse)(nil), + (*Request_Plan)(nil), + (*Request_Apply)(nil), + (*Request_Cancel)(nil), } - file_provisionersdk_proto_provisioner_proto_msgTypes[28].OneofWrappers = []interface{}{ - (*Provision_Response_Log)(nil), - (*Provision_Response_Complete)(nil), + file_provisionersdk_proto_provisioner_proto_msgTypes[23].OneofWrappers = []interface{}{ + (*Response_Log)(nil), + (*Response_Parse)(nil), + (*Response_Plan)(nil), + (*Response_Apply)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -3146,7 +3089,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_provisionersdk_proto_provisioner_proto_rawDesc, NumEnums: 3, - NumMessages: 29, + NumMessages: 27, NumExtensions: 0, NumServices: 1, }, diff --git a/provisionersdk/proto/provisioner.proto b/provisionersdk/proto/provisioner.proto index 789735782f37a..4d1b2c934c8d1 100644 --- a/provisionersdk/proto/provisioner.proto +++ b/provisionersdk/proto/provisioner.proto @@ -168,96 +168,111 @@ message Resource { int32 daily_cost = 8; } -// Parse consumes source-code from a directory to produce inputs. -message Parse { - message Request { - string directory = 1; - } - message Complete { - reserved 2; - - repeated TemplateVariable template_variables = 1; - } - message Response { - oneof type { - Log log = 1; - Complete complete = 2; - } - } -} - +// WorkspaceTransition is the desired outcome of a build enum WorkspaceTransition { START = 0; STOP = 1; DESTROY = 2; } -// Provision consumes source-code from a directory to produce resources. -// Exactly one of Plan or Apply must be provided in a single session. -message Provision { - message Metadata { - string coder_url = 1; - WorkspaceTransition workspace_transition = 2; - string workspace_name = 3; - string workspace_owner = 4; - string workspace_id = 5; - string workspace_owner_id = 6; - string workspace_owner_email = 7; - string template_name = 8; - string template_version = 9; - string workspace_owner_oidc_access_token = 10; - string workspace_owner_session_token = 11; - } +// Metadata is information about a workspace used in the execution of a build +message Metadata { + string coder_url = 1; + WorkspaceTransition workspace_transition = 2; + string workspace_name = 3; + string workspace_owner = 4; + string workspace_id = 5; + string workspace_owner_id = 6; + string workspace_owner_email = 7; + string template_name = 8; + string template_version = 9; + string workspace_owner_oidc_access_token = 10; + string workspace_owner_session_token = 11; +} + +// Config represents execution configuration shared by all subsequent requests in the Session +message Config { + // template_source_archive is a tar of the template source files + bytes template_source_archive = 1; + // state is the provisioner state (if any) + bytes state = 2; + string provisioner_log_level = 3; +} - // Config represents execution configuration shared by both Plan and - // Apply commands. - message Config { - string directory = 1; - bytes state = 2; - Metadata metadata = 3; +// ParseRequest consumes source-code to produce inputs. +message ParseRequest { +} - string provisioner_log_level = 4; - } +// ParseComplete indicates a request to parse completed. +message ParseComplete { + string error = 1; + repeated TemplateVariable template_variables = 2; + bytes readme = 3; +} - message Plan { - reserved 2; +// PlanRequest asks the provisioner to plan what resources & parameters it will create +message PlanRequest { + Metadata metadata = 1; + repeated RichParameterValue rich_parameter_values = 2; + repeated VariableValue variable_values = 3; + repeated GitAuthProvider git_auth_providers = 4; +} - Config config = 1; - repeated RichParameterValue rich_parameter_values = 3; - repeated VariableValue variable_values = 4; - repeated GitAuthProvider git_auth_providers = 5; - } +// PlanComplete indicates a request to plan completed. +message PlanComplete { + string error = 1; + repeated Resource resources = 2; + repeated RichParameter parameters = 3; + repeated string git_auth_providers = 4; +} + +// 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. +message ApplyRequest { + Metadata metadata = 1; +} - message Apply { +// ApplyComplete indicates a request to apply completed. +message ApplyComplete { + bytes state = 1; + string error = 2; + repeated Resource resources = 3; + repeated RichParameter parameters = 4; + repeated string git_auth_providers = 5; +} + +// CancelRequest requests that the previous request be canceled gracefully. +message CancelRequest {} + +message Request { + oneof type { Config config = 1; - bytes plan = 2; + ParseRequest parse = 2; + PlanRequest plan = 3; + ApplyRequest apply = 4; + CancelRequest cancel = 5; } +} - message Cancel {} - message Request { - oneof type { - Plan plan = 1; - Apply apply = 2; - Cancel cancel = 3; - } - } - message Complete { - bytes state = 1; - string error = 2; - repeated Resource resources = 3; - repeated RichParameter parameters = 4; - repeated string git_auth_providers = 5; - bytes plan = 6; - } - message Response { - oneof type { - Log log = 1; - Complete complete = 2; - } +message Response { + oneof type { + Log log = 1; + ParseComplete parse = 2; + PlanComplete plan = 3; + ApplyComplete apply = 4; } } service Provisioner { - rpc Parse(Parse.Request) returns (stream Parse.Response); - rpc Provision(stream Provision.Request) returns (stream Provision.Response); + // 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 + // of zero or more Logs, followed by the corresponding complete message (ParseComplete, PlanComplete, + // ApplyComplete). The daemon may then send a new request. A request to apply MUST be preceded by a request plan, + // and the provisioner should store the plan data on the Session after a successful plan, so that the daemon may + // request an apply. If the daemon closes the Session without an apply, the plan data may be safely discarded. + // + // The daemon may send a CancelRequest, asynchronously to ask the provisioner to cancel the previous ParseRequest, + // PlanRequest, or ApplyRequest. The provisioner MUST reply with a complete message cooresponding to the request + // that was canceled. If the provisioner has already completed the request, it may ignore the CancelRequest. + rpc Session(stream Request) returns (stream Response); } diff --git a/provisionersdk/proto/provisioner_drpc.pb.go b/provisionersdk/proto/provisioner_drpc.pb.go index d307402447c78..06b331bce5f6f 100644 --- a/provisionersdk/proto/provisioner_drpc.pb.go +++ b/provisionersdk/proto/provisioner_drpc.pb.go @@ -38,8 +38,7 @@ func (drpcEncoding_File_provisionersdk_proto_provisioner_proto) JSONUnmarshal(bu type DRPCProvisionerClient interface { DRPCConn() drpc.Conn - Parse(ctx context.Context, in *Parse_Request) (DRPCProvisioner_ParseClient, error) - Provision(ctx context.Context) (DRPCProvisioner_ProvisionClient, error) + Session(ctx context.Context) (DRPCProvisioner_SessionClient, error) } type drpcProvisionerClient struct { @@ -52,115 +51,65 @@ func NewDRPCProvisionerClient(cc drpc.Conn) DRPCProvisionerClient { func (c *drpcProvisionerClient) DRPCConn() drpc.Conn { return c.cc } -func (c *drpcProvisionerClient) Parse(ctx context.Context, in *Parse_Request) (DRPCProvisioner_ParseClient, error) { - stream, err := c.cc.NewStream(ctx, "/provisioner.Provisioner/Parse", drpcEncoding_File_provisionersdk_proto_provisioner_proto{}) +func (c *drpcProvisionerClient) Session(ctx context.Context) (DRPCProvisioner_SessionClient, error) { + stream, err := c.cc.NewStream(ctx, "/provisioner.Provisioner/Session", drpcEncoding_File_provisionersdk_proto_provisioner_proto{}) if err != nil { return nil, err } - x := &drpcProvisioner_ParseClient{stream} - if err := x.MsgSend(in, drpcEncoding_File_provisionersdk_proto_provisioner_proto{}); err != nil { - return nil, err - } - if err := x.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type DRPCProvisioner_ParseClient interface { - drpc.Stream - Recv() (*Parse_Response, error) -} - -type drpcProvisioner_ParseClient struct { - drpc.Stream -} - -func (x *drpcProvisioner_ParseClient) Recv() (*Parse_Response, error) { - m := new(Parse_Response) - if err := x.MsgRecv(m, drpcEncoding_File_provisionersdk_proto_provisioner_proto{}); err != nil { - return nil, err - } - return m, nil -} - -func (x *drpcProvisioner_ParseClient) RecvMsg(m *Parse_Response) error { - return x.MsgRecv(m, drpcEncoding_File_provisionersdk_proto_provisioner_proto{}) -} - -func (c *drpcProvisionerClient) Provision(ctx context.Context) (DRPCProvisioner_ProvisionClient, error) { - stream, err := c.cc.NewStream(ctx, "/provisioner.Provisioner/Provision", drpcEncoding_File_provisionersdk_proto_provisioner_proto{}) - if err != nil { - return nil, err - } - x := &drpcProvisioner_ProvisionClient{stream} + x := &drpcProvisioner_SessionClient{stream} return x, nil } -type DRPCProvisioner_ProvisionClient interface { +type DRPCProvisioner_SessionClient interface { drpc.Stream - Send(*Provision_Request) error - Recv() (*Provision_Response, error) + Send(*Request) error + Recv() (*Response, error) } -type drpcProvisioner_ProvisionClient struct { +type drpcProvisioner_SessionClient struct { drpc.Stream } -func (x *drpcProvisioner_ProvisionClient) Send(m *Provision_Request) error { +func (x *drpcProvisioner_SessionClient) Send(m *Request) error { return x.MsgSend(m, drpcEncoding_File_provisionersdk_proto_provisioner_proto{}) } -func (x *drpcProvisioner_ProvisionClient) Recv() (*Provision_Response, error) { - m := new(Provision_Response) +func (x *drpcProvisioner_SessionClient) Recv() (*Response, error) { + m := new(Response) if err := x.MsgRecv(m, drpcEncoding_File_provisionersdk_proto_provisioner_proto{}); err != nil { return nil, err } return m, nil } -func (x *drpcProvisioner_ProvisionClient) RecvMsg(m *Provision_Response) error { +func (x *drpcProvisioner_SessionClient) RecvMsg(m *Response) error { return x.MsgRecv(m, drpcEncoding_File_provisionersdk_proto_provisioner_proto{}) } type DRPCProvisionerServer interface { - Parse(*Parse_Request, DRPCProvisioner_ParseStream) error - Provision(DRPCProvisioner_ProvisionStream) error + Session(DRPCProvisioner_SessionStream) error } type DRPCProvisionerUnimplementedServer struct{} -func (s *DRPCProvisionerUnimplementedServer) Parse(*Parse_Request, DRPCProvisioner_ParseStream) error { - return drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented) -} - -func (s *DRPCProvisionerUnimplementedServer) Provision(DRPCProvisioner_ProvisionStream) error { +func (s *DRPCProvisionerUnimplementedServer) Session(DRPCProvisioner_SessionStream) error { return drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented) } type DRPCProvisionerDescription struct{} -func (DRPCProvisionerDescription) NumMethods() int { return 2 } +func (DRPCProvisionerDescription) NumMethods() int { return 1 } func (DRPCProvisionerDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) { switch n { case 0: - return "/provisioner.Provisioner/Parse", drpcEncoding_File_provisionersdk_proto_provisioner_proto{}, - func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) { - return nil, srv.(DRPCProvisionerServer). - Parse( - in1.(*Parse_Request), - &drpcProvisioner_ParseStream{in2.(drpc.Stream)}, - ) - }, DRPCProvisionerServer.Parse, true - case 1: - return "/provisioner.Provisioner/Provision", drpcEncoding_File_provisionersdk_proto_provisioner_proto{}, + return "/provisioner.Provisioner/Session", drpcEncoding_File_provisionersdk_proto_provisioner_proto{}, func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) { return nil, srv.(DRPCProvisionerServer). - Provision( - &drpcProvisioner_ProvisionStream{in1.(drpc.Stream)}, + Session( + &drpcProvisioner_SessionStream{in1.(drpc.Stream)}, ) - }, DRPCProvisionerServer.Provision, true + }, DRPCProvisionerServer.Session, true default: return "", nil, nil, nil, false } @@ -170,41 +119,28 @@ func DRPCRegisterProvisioner(mux drpc.Mux, impl DRPCProvisionerServer) error { return mux.Register(impl, DRPCProvisionerDescription{}) } -type DRPCProvisioner_ParseStream interface { - drpc.Stream - Send(*Parse_Response) error -} - -type drpcProvisioner_ParseStream struct { - drpc.Stream -} - -func (x *drpcProvisioner_ParseStream) Send(m *Parse_Response) error { - return x.MsgSend(m, drpcEncoding_File_provisionersdk_proto_provisioner_proto{}) -} - -type DRPCProvisioner_ProvisionStream interface { +type DRPCProvisioner_SessionStream interface { drpc.Stream - Send(*Provision_Response) error - Recv() (*Provision_Request, error) + Send(*Response) error + Recv() (*Request, error) } -type drpcProvisioner_ProvisionStream struct { +type drpcProvisioner_SessionStream struct { drpc.Stream } -func (x *drpcProvisioner_ProvisionStream) Send(m *Provision_Response) error { +func (x *drpcProvisioner_SessionStream) Send(m *Response) error { return x.MsgSend(m, drpcEncoding_File_provisionersdk_proto_provisioner_proto{}) } -func (x *drpcProvisioner_ProvisionStream) Recv() (*Provision_Request, error) { - m := new(Provision_Request) +func (x *drpcProvisioner_SessionStream) Recv() (*Request, error) { + m := new(Request) if err := x.MsgRecv(m, drpcEncoding_File_provisionersdk_proto_provisioner_proto{}); err != nil { return nil, err } return m, nil } -func (x *drpcProvisioner_ProvisionStream) RecvMsg(m *Provision_Request) error { +func (x *drpcProvisioner_SessionStream) RecvMsg(m *Request) error { return x.MsgRecv(m, drpcEncoding_File_provisionersdk_proto_provisioner_proto{}) } From a29592ab53d720541d67f62a7229b95165ec1964 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Wed, 23 Aug 2023 08:18:59 +0000 Subject: [PATCH 02/13] refactor provisioners to use new protocol Signed-off-by: Spike Curtis --- provisioner/echo/serve.go | 293 +++++----- provisioner/echo/serve_test.go | 306 ++++++----- provisioner/terraform/executor.go | 122 ++--- .../terraform/executor_internal_test.go | 4 +- provisioner/terraform/parse.go | 22 +- provisioner/terraform/parse_test.go | 210 +++---- provisioner/terraform/provision.go | 253 ++++----- provisioner/terraform/provision_test.go | 518 ++++++++---------- provisioner/terraform/serve.go | 2 +- provisioner/terraform/testdata/fake_cancel.sh | 15 +- .../terraform/testdata/fake_cancel_hang.sh | 12 +- provisionersdk/errors.go | 19 + provisionersdk/serve.go | 27 +- provisionersdk/serve_test.go | 52 +- provisionersdk/session.go | 298 ++++++++++ provisionersdk/transport.go | 2 +- 16 files changed, 1204 insertions(+), 951 deletions(-) create mode 100644 provisionersdk/errors.go create mode 100644 provisionersdk/session.go diff --git a/provisioner/echo/serve.go b/provisioner/echo/serve.go index c057254704f3d..5f4b6f2e95edf 100644 --- a/provisioner/echo/serve.go +++ b/provisioner/echo/serve.go @@ -5,25 +5,24 @@ import ( "bytes" "context" "fmt" + "os" "path/filepath" "strings" + "github.com/google/uuid" "golang.org/x/xerrors" protobuf "google.golang.org/protobuf/proto" - "github.com/google/uuid" - "github.com/spf13/afero" - "github.com/coder/coder/v2/provisionersdk" "github.com/coder/coder/v2/provisionersdk/proto" ) // ProvisionApplyWithAgent returns provision responses that will mock a fake // "aws_instance" resource with an agent that has the given auth token. -func ProvisionApplyWithAgent(authToken string) []*proto.Provision_Response { - return []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ +func ProvisionApplyWithAgent(authToken string) []*proto.Response { + return []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -42,23 +41,36 @@ func ProvisionApplyWithAgent(authToken string) []*proto.Provision_Response { var ( // ParseComplete is a helper to indicate an empty parse completion. - ParseComplete = []*proto.Parse_Response{{ - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{}, + ParseComplete = []*proto.Response{{ + Type: &proto.Response_Parse{ + Parse: &proto.ParseComplete{}, + }, + }} + // PlanComplete is a helper to indicate an empty provision completion. + PlanComplete = []*proto.Response{{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{}, }, }} - // ProvisionComplete is a helper to indicate an empty provision completion. - ProvisionComplete = []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, + // ApplyComplete is a helper to indicate an empty provision completion. + ApplyComplete = []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{}, }, }} - // ProvisionFailed is a helper to convey a failed provision - // operation. - ProvisionFailed = []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + // PlanFailed is a helper to convey a failed plan operation + PlanFailed = []*proto.Response{{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ + Error: "failed!", + }, + }, + }} + // ApplyFailed is a helper to convey a failed apply operation + ApplyFailed = []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Error: "failed!", }, }, @@ -66,120 +78,118 @@ var ( ) // Serve starts the echo provisioner. -func Serve(ctx context.Context, filesystem afero.Fs, options *provisionersdk.ServeOptions) error { - return provisionersdk.Serve(ctx, &echo{ - filesystem: filesystem, - }, options) +func Serve(ctx context.Context, options *provisionersdk.ServeOptions) error { + return provisionersdk.Serve(ctx, &echo{}, options) } // The echo provisioner serves as a dummy provisioner primarily // used for testing. It echos responses from JSON files in the // format %d.protobuf. It's used for testing. -type echo struct { - filesystem afero.Fs -} +type echo struct{} -// Parse reads requests from the provided directory to stream responses. -func (e *echo) Parse(request *proto.Parse_Request, stream proto.DRPCProvisioner_ParseStream) error { - for index := 0; ; index++ { - path := filepath.Join(request.Directory, fmt.Sprintf("%d.parse.protobuf", index)) - _, err := e.filesystem.Stat(path) - if err != nil { - if index == 0 { - // Error if nothing is around to enable failed states. - return xerrors.Errorf("no state: %w", err) - } - break - } - data, err := afero.ReadFile(e.filesystem, path) - if err != nil { - return xerrors.Errorf("read file %q: %w", path, err) - } - var response proto.Parse_Response - err = protobuf.Unmarshal(data, &response) - if err != nil { - return xerrors.Errorf("unmarshal: %w", err) - } - err = stream.Send(&response) - if err != nil { - return err - } - } - <-stream.Context().Done() - return stream.Context().Err() -} - -// Provision reads requests from the provided directory to stream responses. -func (e *echo) Provision(stream proto.DRPCProvisioner_ProvisionStream) error { - msg, err := stream.Recv() - if err != nil { - return err - } - - var config *proto.Provision_Config - switch { - case msg.GetPlan() != nil: - config = msg.GetPlan().GetConfig() - case msg.GetApply() != nil: - config = msg.GetApply().GetConfig() - default: - // Probably a cancel - return nil - } - -outer: +func readResponses(sess *provisionersdk.Session, trans string, suffix string) ([]*proto.Response, error) { + var responses []*proto.Response for i := 0; ; i++ { - var extension string - if msg.GetPlan() != nil { - extension = ".plan.protobuf" - } else { - extension = ".apply.protobuf" - } - var ( - path string - pathIndex int - ) - // Try more specific path first, then fallback to generic. paths := []string{ - filepath.Join(config.Directory, fmt.Sprintf("%d.%s.provision"+extension, i, strings.ToLower(config.GetMetadata().GetWorkspaceTransition().String()))), - filepath.Join(config.Directory, fmt.Sprintf("%d.provision"+extension, i)), + // Try more specific path first, then fallback to generic. + filepath.Join(sess.WorkDirectory, fmt.Sprintf("%d.%s.%s", i, trans, suffix)), + filepath.Join(sess.WorkDirectory, fmt.Sprintf("%d.%s", i, suffix)), } - for pathIndex, path = range paths { - _, err := e.filesystem.Stat(path) - if err != nil && pathIndex == len(paths)-1 { - // If there are zero messages, something is wrong. + for pathIndex, path := range paths { + _, err := os.Stat(path) + if err != nil && pathIndex == (len(paths)-1) { + // If there are zero messages, something is wrong if i == 0 { // Error if nothing is around to enable failed states. - return xerrors.New("no state") + return nil, xerrors.Errorf("no state: %w", err) } - // Otherwise, we're done with the entire provision. - break outer - } else if err != nil { + // Otherwise, we've read all responses + return responses, nil + } + if err != nil { + // try next path continue } + data, err := os.ReadFile(path) + if err != nil { + return nil, xerrors.Errorf("read file %q: %w", path, err) + } + response := new(proto.Response) + err = protobuf.Unmarshal(data, response) + if err != nil { + return nil, xerrors.Errorf("unmarshal: %w", err) + } + responses = append(responses, response) break } - data, err := afero.ReadFile(e.filesystem, path) - if err != nil { - return xerrors.Errorf("read file %q: %w", path, err) + } + return responses, nil +} + +// Parse reads requests from the provided directory to stream responses. +func (e *echo) Parse(sess *provisionersdk.Session, _ *proto.ParseRequest, _ <-chan struct{}) *proto.ParseComplete { + responses, err := readResponses(sess, "unspecified", "parse.protobuf") + if err != nil { + return &proto.ParseComplete{Error: err.Error()} + } + for _, response := range responses { + if log := response.GetLog(); log != nil { + sess.ProvisionLog(log.Level, log.Output) } - var response proto.Provision_Response - err = protobuf.Unmarshal(data, &response) - if err != nil { - return xerrors.Errorf("unmarshal: %w", err) + if complete := response.GetParse(); complete != nil { + return complete + } + } + + // if we didn't get a complete from the filesystem, that's an error + return provisionersdk.ParseErrorf("complete response missing") +} + +// Plan reads requests from the provided directory to stream responses. +func (e *echo) Plan(sess *provisionersdk.Session, req *proto.PlanRequest, canceledOrComplete <-chan struct{}) *proto.PlanComplete { + responses, err := readResponses( + sess, + strings.ToLower(req.GetMetadata().GetWorkspaceTransition().String()), + "plan.protobuf") + if err != nil { + return &proto.PlanComplete{Error: err.Error()} + } + for _, response := range responses { + if log := response.GetLog(); log != nil { + sess.ProvisionLog(log.Level, log.Output) } - r, ok := filterLogResponses(config, &response) - if !ok { - continue + if complete := response.GetPlan(); complete != nil { + return complete } + } - err = stream.Send(r) - if err != nil { - return err + // some tests use Echo without a complete response to test cancel + <-canceledOrComplete + return provisionersdk.PlanErrorf("canceled") +} + +// Apply reads requests from the provided directory to stream responses. +func (e *echo) Apply(sess *provisionersdk.Session, req *proto.ApplyRequest, canceledOrComplete <-chan struct{}) *proto.ApplyComplete { + responses, err := readResponses( + sess, + strings.ToLower(req.GetMetadata().GetWorkspaceTransition().String()), + "apply.protobuf") + if err != nil { + return &proto.ApplyComplete{Error: err.Error()} + } + for _, response := range responses { + if log := response.GetLog(); log != nil { + sess.ProvisionLog(log.Level, log.Output) + } + if complete := response.GetApply(); complete != nil { + return complete } } - <-stream.Context().Done() - return stream.Context().Err() + + // some tests use Echo without a complete response to test cancel + <-canceledOrComplete + // we have to return a clean Complete or the status will go to "failed" + return provisionersdk.ApplyErrorf("canceled") } func (*echo) Shutdown(_ context.Context, _ *proto.Empty) (*proto.Empty, error) { @@ -188,29 +198,42 @@ func (*echo) Shutdown(_ context.Context, _ *proto.Empty) (*proto.Empty, error) { // Responses is a collection of mocked responses to Provision operations. type Responses struct { - Parse []*proto.Parse_Response + Parse []*proto.Response // ProvisionApply and ProvisionPlan are used to mock ALL responses of // Apply and Plan, regardless of transition. - ProvisionApply []*proto.Provision_Response - ProvisionPlan []*proto.Provision_Response + ProvisionApply []*proto.Response + ProvisionPlan []*proto.Response // ProvisionApplyMap and ProvisionPlanMap are used to mock specific // transition responses. They are prioritized over the generic responses. - ProvisionApplyMap map[proto.WorkspaceTransition][]*proto.Provision_Response - ProvisionPlanMap map[proto.WorkspaceTransition][]*proto.Provision_Response + ProvisionApplyMap map[proto.WorkspaceTransition][]*proto.Response + ProvisionPlanMap map[proto.WorkspaceTransition][]*proto.Response } // Tar returns a tar archive of responses to provisioner operations. func Tar(responses *Responses) ([]byte, error) { if responses == nil { responses = &Responses{ - ParseComplete, ProvisionComplete, ProvisionComplete, + ParseComplete, ApplyComplete, PlanComplete, nil, nil, } } if responses.ProvisionPlan == nil { - responses.ProvisionPlan = responses.ProvisionApply + for _, resp := range responses.ProvisionApply { + if resp.GetLog() != nil { + responses.ProvisionPlan = append(responses.ProvisionPlan, resp) + continue + } + responses.ProvisionPlan = append(responses.ProvisionPlan, &proto.Response{ + Type: &proto.Response_Plan{Plan: &proto.PlanComplete{ + Error: resp.GetApply().GetError(), + Resources: resp.GetApply().GetResources(), + Parameters: resp.GetApply().GetParameters(), + GitAuthProviders: resp.GetApply().GetGitAuthProviders(), + }}, + }) + } } var buffer bytes.Buffer @@ -245,20 +268,20 @@ func Tar(responses *Responses) ([]byte, error) { } } for index, response := range responses.ProvisionApply { - err := writeProto(fmt.Sprintf("%d.provision.apply.protobuf", index), response) + err := writeProto(fmt.Sprintf("%d.apply.protobuf", index), response) if err != nil { return nil, err } } for index, response := range responses.ProvisionPlan { - err := writeProto(fmt.Sprintf("%d.provision.plan.protobuf", index), response) + err := writeProto(fmt.Sprintf("%d.plan.protobuf", index), response) if err != nil { return nil, err } } for trans, m := range responses.ProvisionApplyMap { for i, rs := range m { - err := writeProto(fmt.Sprintf("%d.%s.provision.apply.protobuf", i, strings.ToLower(trans.String())), rs) + err := writeProto(fmt.Sprintf("%d.%s.apply.protobuf", i, strings.ToLower(trans.String())), rs) if err != nil { return nil, err } @@ -266,7 +289,7 @@ func Tar(responses *Responses) ([]byte, error) { } for trans, m := range responses.ProvisionPlanMap { for i, rs := range m { - err := writeProto(fmt.Sprintf("%d.%s.provision.plan.protobuf", i, strings.ToLower(trans.String())), rs) + err := writeProto(fmt.Sprintf("%d.%s.plan.protobuf", i, strings.ToLower(trans.String())), rs) if err != nil { return nil, err } @@ -279,22 +302,14 @@ func Tar(responses *Responses) ([]byte, error) { return buffer.Bytes(), nil } -func filterLogResponses(config *proto.Provision_Config, response *proto.Provision_Response) (*proto.Provision_Response, bool) { - responseLog, ok := response.Type.(*proto.Provision_Response_Log) - if !ok { - // Pass all non-log responses - return response, true - } - - if config.ProvisionerLogLevel == "" { - // Don't change the default behavior of "echo" - return response, true - } - - provisionerLogLevel := proto.LogLevel_value[strings.ToUpper(config.ProvisionerLogLevel)] - if int32(responseLog.Log.Level) < provisionerLogLevel { - // Log level is not enabled - return nil, false +func WithResources(resources []*proto.Resource) *Responses { + return &Responses{ + Parse: ParseComplete, + ProvisionApply: []*proto.Response{{Type: &proto.Response_Apply{Apply: &proto.ApplyComplete{ + Resources: resources, + }}}}, + ProvisionPlan: []*proto.Response{{Type: &proto.Response_Plan{Plan: &proto.PlanComplete{ + Resources: resources, + }}}}, } - return response, true } diff --git a/provisioner/echo/serve_test.go b/provisioner/echo/serve_test.go index 01b283f8a55f5..622f785da7074 100644 --- a/provisioner/echo/serve_test.go +++ b/provisioner/echo/serve_test.go @@ -1,27 +1,23 @@ package echo_test import ( - "archive/tar" - "bytes" "context" - "io" - "os" - "path/filepath" "testing" - "github.com/spf13/afero" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/coder/coder/v2/provisioner/echo" "github.com/coder/coder/v2/provisionersdk" "github.com/coder/coder/v2/provisionersdk/proto" + "github.com/coder/coder/v2/testutil" ) func TestEcho(t *testing.T) { t.Parallel() - fs := afero.NewMemMapFs() + workdir := t.TempDir() + // Create an in-memory provisioner to communicate with. client, server := provisionersdk.MemTransportPipe() ctx, cancelFunc := context.WithCancel(context.Background()) @@ -31,8 +27,9 @@ func TestEcho(t *testing.T) { cancelFunc() }) go func() { - err := echo.Serve(ctx, fs, &provisionersdk.ServeOptions{ - Listener: server, + err := echo.Serve(ctx, &provisionersdk.ServeOptions{ + Listener: server, + WorkDirectory: workdir, }) assert.NoError(t, err) }() @@ -40,26 +37,38 @@ func TestEcho(t *testing.T) { t.Run("Parse", func(t *testing.T) { t.Parallel() + ctx, cancel := context.WithTimeout(ctx, testutil.WaitShort) + defer cancel() - responses := []*proto.Parse_Response{{ - Type: &proto.Parse_Response_Log{ - Log: &proto.Log{ - Output: "log-output", + responses := []*proto.Response{ + { + Type: &proto.Response_Log{ + Log: &proto.Log{ + Output: "log-output", + }, }, }, - }, { - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{}, - }, - }} + { + Type: &proto.Response_Parse{ + Parse: &proto.ParseComplete{}, + }, + }} data, err := echo.Tar(&echo.Responses{ Parse: responses, }) require.NoError(t, err) - client, err := api.Parse(ctx, &proto.Parse_Request{ - Directory: unpackTar(t, fs, data), - }) + client, err := api.Session(ctx) require.NoError(t, err) + defer func() { + err := client.Close() + require.NoError(t, err) + }() + err = client.Send(&proto.Request{Type: &proto.Request_Config{Config: &proto.Config{ + TemplateSourceArchive: data, + }}}) + require.NoError(t, err) + + err = client.Send(&proto.Request{Type: &proto.Request_Parse{Parse: &proto.ParseRequest{}}}) log, err := client.Recv() require.NoError(t, err) require.Equal(t, responses[0].GetLog().Output, log.GetLog().Output) @@ -70,95 +79,117 @@ func TestEcho(t *testing.T) { t.Run("Provision", func(t *testing.T) { t.Parallel() + ctx, cancel := context.WithTimeout(ctx, testutil.WaitShort) + defer cancel() - responses := []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Log{ - Log: &proto.Log{ - Level: proto.LogLevel_INFO, - Output: "log-output", + planResponses := []*proto.Response{ + { + Type: &proto.Response_Log{ + Log: &proto.Log{ + Level: proto.LogLevel_INFO, + Output: "log-output", + }, }, }, - }, { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Resources: []*proto.Resource{{ - Name: "resource", - }}, + { + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ + Resources: []*proto.Resource{{ + Name: "resource", + }}, + }, }, }, - }} - data, err := echo.Tar(&echo.Responses{ - ProvisionApply: responses, - }) - require.NoError(t, err) - client, err := api.Provision(ctx) - require.NoError(t, err) - err = client.Send(&proto.Provision_Request{ - Type: &proto.Provision_Request_Plan{ - Plan: &proto.Provision_Plan{ - Config: &proto.Provision_Config{ - Directory: unpackTar(t, fs, data), + } + applyResponses := []*proto.Response{ + { + Type: &proto.Response_Log{ + Log: &proto.Log{ + Level: proto.LogLevel_INFO, + Output: "log-output", + }, + }, + }, + { + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ + Resources: []*proto.Resource{{ + Name: "resource", + }}, }, }, }, + } + data, err := echo.Tar(&echo.Responses{ + ProvisionPlan: planResponses, + ProvisionApply: applyResponses, }) require.NoError(t, err) + client, err := api.Session(ctx) + require.NoError(t, err) + defer func() { + err := client.Close() + require.NoError(t, err) + }() + err = client.Send(&proto.Request{Type: &proto.Request_Config{Config: &proto.Config{ + TemplateSourceArchive: data, + }}}) + require.NoError(t, err) + + err = client.Send(&proto.Request{Type: &proto.Request_Plan{Plan: &proto.PlanRequest{}}}) + require.NoError(t, err) log, err := client.Recv() require.NoError(t, err) - require.Equal(t, responses[0].GetLog().Output, log.GetLog().Output) + require.Equal(t, planResponses[0].GetLog().Output, log.GetLog().Output) complete, err := client.Recv() require.NoError(t, err) - require.Equal(t, responses[1].GetComplete().Resources[0].Name, - complete.GetComplete().Resources[0].Name) + require.Equal(t, planResponses[1].GetPlan().Resources[0].Name, + complete.GetPlan().Resources[0].Name) + + err = client.Send(&proto.Request{Type: &proto.Request_Apply{Apply: &proto.ApplyRequest{}}}) + require.NoError(t, err) + log, err = client.Recv() + require.NoError(t, err) + require.Equal(t, applyResponses[0].GetLog().Output, log.GetLog().Output) + complete, err = client.Recv() + require.NoError(t, err) + require.Equal(t, applyResponses[1].GetApply().Resources[0].Name, + complete.GetApply().Resources[0].Name) }) t.Run("ProvisionStop", func(t *testing.T) { t.Parallel() // Stop responses should be returned when the workspace is being stopped. - - defaultResponses := []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Resources: []*proto.Resource{{ - Name: "DEFAULT", - }}, - }, - }, - }} - stopResponses := []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Resources: []*proto.Resource{{ - Name: "STOP", - }}, - }, - }, - }} data, err := echo.Tar(&echo.Responses{ - ProvisionApply: defaultResponses, - ProvisionPlan: defaultResponses, - ProvisionPlanMap: map[proto.WorkspaceTransition][]*proto.Provision_Response{ - proto.WorkspaceTransition_STOP: stopResponses, + ProvisionApply: applyCompleteResource("DEFAULT"), + ProvisionPlan: planCompleteResource("DEFAULT"), + ProvisionPlanMap: map[proto.WorkspaceTransition][]*proto.Response{ + proto.WorkspaceTransition_STOP: planCompleteResource("STOP"), }, - ProvisionApplyMap: map[proto.WorkspaceTransition][]*proto.Provision_Response{ - proto.WorkspaceTransition_STOP: stopResponses, + ProvisionApplyMap: map[proto.WorkspaceTransition][]*proto.Response{ + proto.WorkspaceTransition_STOP: applyCompleteResource("STOP"), }, }) require.NoError(t, err) - client, err := api.Provision(ctx) + client, err := api.Session(ctx) + require.NoError(t, err) + defer func() { + err := client.Close() + require.NoError(t, err) + }() + err = client.Send(&proto.Request{Type: &proto.Request_Config{Config: &proto.Config{ + TemplateSourceArchive: data, + }}}) require.NoError(t, err) // Do stop. - err = client.Send(&proto.Provision_Request{ - Type: &proto.Provision_Request_Plan{ - Plan: &proto.Provision_Plan{ - Config: &proto.Provision_Config{ - Directory: unpackTar(t, fs, data), - Metadata: &proto.Provision_Metadata{ - WorkspaceTransition: proto.WorkspaceTransition_STOP, - }, + err = client.Send(&proto.Request{ + Type: &proto.Request_Plan{ + Plan: &proto.PlanRequest{ + Metadata: &proto.Metadata{ + WorkspaceTransition: proto.WorkspaceTransition_STOP, }, }, }, @@ -168,22 +199,16 @@ func TestEcho(t *testing.T) { complete, err := client.Recv() require.NoError(t, err) require.Equal(t, - stopResponses[0].GetComplete().Resources[0].Name, - complete.GetComplete().Resources[0].Name, + "STOP", + complete.GetPlan().Resources[0].Name, ) // Do start. - client, err = api.Provision(ctx) - require.NoError(t, err) - - err = client.Send(&proto.Provision_Request{ - Type: &proto.Provision_Request_Plan{ - Plan: &proto.Provision_Plan{ - Config: &proto.Provision_Config{ - Directory: unpackTar(t, fs, data), - Metadata: &proto.Provision_Metadata{ - WorkspaceTransition: proto.WorkspaceTransition_START, - }, + err = client.Send(&proto.Request{ + Type: &proto.Request_Plan{ + Plan: &proto.PlanRequest{ + Metadata: &proto.Metadata{ + WorkspaceTransition: proto.WorkspaceTransition_START, }, }, }, @@ -193,31 +218,33 @@ func TestEcho(t *testing.T) { complete, err = client.Recv() require.NoError(t, err) require.Equal(t, - defaultResponses[0].GetComplete().Resources[0].Name, - complete.GetComplete().Resources[0].Name, + "DEFAULT", + complete.GetPlan().Resources[0].Name, ) }) t.Run("ProvisionWithLogLevel", func(t *testing.T) { t.Parallel() + ctx, cancel := context.WithTimeout(ctx, testutil.WaitShort) + defer cancel() - responses := []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Log{ + responses := []*proto.Response{{ + Type: &proto.Response_Log{ Log: &proto.Log{ Level: proto.LogLevel_TRACE, Output: "log-output-trace", }, }, }, { - Type: &proto.Provision_Response_Log{ + Type: &proto.Response_Log{ Log: &proto.Log{ Level: proto.LogLevel_INFO, Output: "log-output-info", }, }, }, { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "resource", }}, @@ -225,49 +252,62 @@ func TestEcho(t *testing.T) { }, }} data, err := echo.Tar(&echo.Responses{ + ProvisionPlan: echo.PlanComplete, ProvisionApply: responses, }) require.NoError(t, err) - client, err := api.Provision(ctx) + client, err := api.Session(ctx) require.NoError(t, err) - err = client.Send(&proto.Provision_Request{ - Type: &proto.Provision_Request_Plan{ - Plan: &proto.Provision_Plan{ - Config: &proto.Provision_Config{ - Directory: unpackTar(t, fs, data), - ProvisionerLogLevel: "debug", - }, - }, - }, - }) + defer func() { + err := client.Close() + require.NoError(t, err) + }() + err = client.Send(&proto.Request{Type: &proto.Request_Config{Config: &proto.Config{ + TemplateSourceArchive: data, + ProvisionerLogLevel: "debug", + }}}) + require.NoError(t, err) + + // Plan is required before apply + err = client.Send(&proto.Request{Type: &proto.Request_Plan{Plan: &proto.PlanRequest{}}}) + require.NoError(t, err) + complete, err := client.Recv() + require.NoError(t, err) + require.NotNil(t, complete.GetPlan()) + + err = client.Send(&proto.Request{Type: &proto.Request_Apply{Apply: &proto.ApplyRequest{}}}) require.NoError(t, err) log, err := client.Recv() require.NoError(t, err) // Skip responses[0] as it's trace level require.Equal(t, responses[1].GetLog().Output, log.GetLog().Output) - complete, err := client.Recv() + complete, err = client.Recv() require.NoError(t, err) - require.Equal(t, responses[2].GetComplete().Resources[0].Name, - complete.GetComplete().Resources[0].Name) + require.Equal(t, responses[2].GetApply().Resources[0].Name, + complete.GetApply().Resources[0].Name) }) } -func unpackTar(t *testing.T, fs afero.Fs, data []byte) string { - directory := t.TempDir() - reader := tar.NewReader(bytes.NewReader(data)) - for { - header, err := reader.Next() - if err != nil { - break - } - // #nosec - path := filepath.Join(directory, header.Name) - file, err := fs.OpenFile(path, os.O_CREATE|os.O_RDWR, 0o600) - require.NoError(t, err) - _, err = io.CopyN(file, reader, 1<<20) - require.ErrorIs(t, err, io.EOF) - err = file.Close() - require.NoError(t, err) - } - return directory +func planCompleteResource(name string) []*proto.Response { + return []*proto.Response{{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ + Resources: []*proto.Resource{{ + Name: name, + }}, + }, + }, + }} +} + +func applyCompleteResource(name string) []*proto.Response { + return []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ + Resources: []*proto.Resource{{ + Name: name, + }}, + }, + }, + }} } diff --git a/provisioner/terraform/executor.go b/provisioner/terraform/executor.go index f006dcd149daa..e610652d714b0 100644 --- a/provisioner/terraform/executor.go +++ b/provisioner/terraform/executor.go @@ -25,6 +25,7 @@ import ( ) type executor struct { + logger slog.Logger server *server mut *sync.Mutex binaryPath string @@ -50,8 +51,10 @@ func (e *executor) execWriteOutput(ctx, killCtx context.Context, args, env []str ctx, span := e.server.startTrace(ctx, fmt.Sprintf("exec - terraform %s", args[0])) defer span.End() span.SetAttributes(attribute.StringSlice("args", args)) + e.logger.Debug(ctx, "starting command", slog.F("args", args)) defer func() { + e.logger.Debug(ctx, "closing writers", slog.Error(err)) closeErr := stdOutWriter.Close() if err == nil && closeErr != nil { err = closeErr @@ -62,6 +65,7 @@ func (e *executor) execWriteOutput(ctx, killCtx context.Context, args, env []str } }() if ctx.Err() != nil { + e.logger.Debug(ctx, "context canceled before command started", slog.F("args", args)) return ctx.Err() } @@ -90,11 +94,14 @@ func (e *executor) execWriteOutput(ctx, killCtx context.Context, args, env []str ) err = cmd.Start() if err != nil { + e.logger.Debug(ctx, "failed to start command", slog.F("args", args)) return err } - interruptCommandOnCancel(ctx, killCtx, cmd) + interruptCommandOnCancel(ctx, killCtx, e.logger, cmd) - return cmd.Wait() + err = cmd.Wait() + e.logger.Debug(ctx, "command done", slog.F("args", args), slog.Error(err)) + return err } // execParseJSON must only be called while the lock is held. @@ -120,7 +127,7 @@ func (e *executor) execParseJSON(ctx, killCtx context.Context, args, env []strin if err != nil { return err } - interruptCommandOnCancel(ctx, killCtx, cmd) + interruptCommandOnCancel(ctx, killCtx, e.logger, cmd) err = cmd.Wait() if err != nil { @@ -207,15 +214,23 @@ func (e *executor) init(ctx, killCtx context.Context, logr logSink) error { return e.execWriteOutput(ctx, killCtx, args, e.basicEnv(), outWriter, errWriter) } +func getPlanFilePath(workdir string) string { + return filepath.Join(workdir, "terraform.tfplan") +} + +func getStateFilePath(workdir string) string { + return filepath.Join(workdir, "terraform.tfstate") +} + // revive:disable-next-line:flag-parameter -func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr logSink, destroy bool) (*proto.Provision_Response, error) { +func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr logSink, destroy bool) (*proto.PlanComplete, error) { ctx, span := e.server.startTrace(ctx, tracing.FuncName()) defer span.End() e.mut.Lock() defer e.mut.Unlock() - planfilePath := filepath.Join(e.workdir, "terraform.tfplan") + planfilePath := getPlanFilePath(e.workdir) args := []string{ "plan", "-no-color", @@ -248,19 +263,10 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l if err != nil { return nil, err } - planFileByt, err := os.ReadFile(planfilePath) - if err != nil { - return nil, err - } - return &proto.Provision_Response{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Parameters: state.Parameters, - Resources: state.Resources, - GitAuthProviders: state.GitAuthProviders, - Plan: planFileByt, - }, - }, + return &proto.PlanComplete{ + Parameters: state.Parameters, + Resources: state.Resources, + GitAuthProviders: state.GitAuthProviders, }, nil } @@ -344,7 +350,7 @@ func (e *executor) graph(ctx, killCtx context.Context) (string, error) { if err != nil { return "", err } - interruptCommandOnCancel(ctx, killCtx, cmd) + interruptCommandOnCancel(ctx, killCtx, e.logger, cmd) err = cmd.Wait() if err != nil { @@ -355,33 +361,22 @@ func (e *executor) graph(ctx, killCtx context.Context) (string, error) { func (e *executor) apply( ctx, killCtx context.Context, - plan []byte, env []string, logr logSink, -) (*proto.Provision_Response, error) { +) (*proto.ApplyComplete, error) { ctx, span := e.server.startTrace(ctx, tracing.FuncName()) defer span.End() e.mut.Lock() defer e.mut.Unlock() - planFile, err := os.CreateTemp("", "coder-terrafrom-plan") - if err != nil { - return nil, xerrors.Errorf("create plan file: %w", err) - } - _, err = planFile.Write(plan) - if err != nil { - return nil, xerrors.Errorf("write plan file: %w", err) - } - defer os.Remove(planFile.Name()) - args := []string{ "apply", "-no-color", "-auto-approve", "-input=false", "-json", - planFile.Name(), + getPlanFilePath(e.workdir), } outWriter, doneOut := provisionLogWriter(logr) @@ -393,7 +388,7 @@ func (e *executor) apply( <-doneErr }() - err = e.execWriteOutput(ctx, killCtx, args, env, outWriter, errWriter) + err := e.execWriteOutput(ctx, killCtx, args, env, outWriter, errWriter) if err != nil { return nil, xerrors.Errorf("terraform apply: %w", err) } @@ -406,15 +401,11 @@ func (e *executor) apply( if err != nil { return nil, xerrors.Errorf("read statefile %q: %w", statefilePath, err) } - return &proto.Provision_Response{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Parameters: state.Parameters, - Resources: state.Resources, - GitAuthProviders: state.GitAuthProviders, - State: stateContent, - }, - }, + return &proto.ApplyComplete{ + Parameters: state.Parameters, + Resources: state.Resources, + GitAuthProviders: state.GitAuthProviders, + State: stateContent, }, nil } @@ -459,48 +450,28 @@ func (e *executor) state(ctx, killCtx context.Context) (*tfjson.State, error) { return state, nil } -func interruptCommandOnCancel(ctx, killCtx context.Context, cmd *exec.Cmd) { +func interruptCommandOnCancel(ctx, killCtx context.Context, logger slog.Logger, cmd *exec.Cmd) { go func() { select { case <-ctx.Done(): + var err error switch runtime.GOOS { case "windows": // Interrupts aren't supported by Windows. - _ = cmd.Process.Kill() + err = cmd.Process.Kill() default: - _ = cmd.Process.Signal(os.Interrupt) + err = cmd.Process.Signal(os.Interrupt) } + logger.Debug(ctx, "interrupted command", slog.F("args", cmd.Args), slog.Error(err)) case <-killCtx.Done(): + logger.Debug(ctx, "kill context ended", slog.F("args", cmd.Args)) } }() } type logSink interface { - Log(*proto.Log) -} - -type streamLogSink struct { - // Any errors writing to the stream will be logged to logger. - logger slog.Logger - stream proto.DRPCProvisioner_ProvisionStream -} - -var _ logSink = streamLogSink{} - -func (s streamLogSink) Log(l *proto.Log) { - err := s.stream.Send(&proto.Provision_Response{ - Type: &proto.Provision_Response_Log{ - Log: l, - }, - }) - if err != nil { - s.logger.Warn(context.Background(), "write log to stream", - slog.F("level", l.Level.String()), - slog.F("message", l.Output), - slog.Error(err), - ) - } + ProvisionLog(l proto.LogLevel, o string) } // logWriter creates a WriteCloser that will log each line of text at the given level. The WriteCloser must be closed @@ -524,7 +495,7 @@ func readAndLog(sink logSink, r io.Reader, done chan<- any, level proto.LogLevel continue } - sink.Log(&proto.Log{Level: level, Output: scanner.Text()}) + sink.ProvisionLog(level, scanner.Text()) continue } @@ -541,7 +512,7 @@ func readAndLog(sink logSink, r io.Reader, done chan<- any, level proto.LogLevel if logLevel == proto.LogLevel_INFO { logLevel = proto.LogLevel_DEBUG } - sink.Log(&proto.Log{Level: logLevel, Output: log.Message}) + sink.ProvisionLog(logLevel, log.Message) } } @@ -586,7 +557,7 @@ func provisionReadAndLog(sink logSink, r io.Reader, done chan<- any) { } logLevel := convertTerraformLogLevel(log.Level, sink) - sink.Log(&proto.Log{Level: logLevel, Output: log.Message}) + sink.ProvisionLog(logLevel, log.Message) // If the diagnostic is provided, let's provide a bit more info! if log.Diagnostic == nil { @@ -594,7 +565,7 @@ func provisionReadAndLog(sink logSink, r io.Reader, done chan<- any) { } logLevel = convertTerraformLogLevel(string(log.Diagnostic.Severity), sink) for _, diagLine := range strings.Split(FormatDiagnostic(log.Diagnostic), "\n") { - sink.Log(&proto.Log{Level: logLevel, Output: diagLine}) + sink.ProvisionLog(logLevel, diagLine) } } } @@ -612,10 +583,7 @@ func convertTerraformLogLevel(logLevel string, sink logSink) proto.LogLevel { case "error": return proto.LogLevel_ERROR default: - sink.Log(&proto.Log{ - Level: proto.LogLevel_WARN, - Output: fmt.Sprintf("unable to convert log level %s", logLevel), - }) + sink.ProvisionLog(proto.LogLevel_WARN, fmt.Sprintf("unable to convert log level %s", logLevel)) return proto.LogLevel_INFO } } diff --git a/provisioner/terraform/executor_internal_test.go b/provisioner/terraform/executor_internal_test.go index 18f130f57bc3b..523099249d2ae 100644 --- a/provisioner/terraform/executor_internal_test.go +++ b/provisioner/terraform/executor_internal_test.go @@ -14,8 +14,8 @@ type mockLogger struct { var _ logSink = &mockLogger{} -func (m *mockLogger) Log(l *proto.Log) { - m.logs = append(m.logs, l) +func (m *mockLogger) ProvisionLog(l proto.LogLevel, o string) { + m.logs = append(m.logs, &proto.Log{Level: l, Output: o}) } func TestLogWriter_Mainline(t *testing.T) { diff --git a/provisioner/terraform/parse.go b/provisioner/terraform/parse.go index 6c52dc1313e1e..10ab7b801b071 100644 --- a/provisioner/terraform/parse.go +++ b/provisioner/terraform/parse.go @@ -12,18 +12,20 @@ import ( "golang.org/x/xerrors" "github.com/coder/coder/v2/coderd/tracing" + "github.com/coder/coder/v2/provisionersdk" "github.com/coder/coder/v2/provisionersdk/proto" ) // Parse extracts Terraform variables from source-code. -func (s *server) Parse(request *proto.Parse_Request, stream proto.DRPCProvisioner_ParseStream) error { - _, span := s.startTrace(stream.Context(), tracing.FuncName()) +func (s *server) Parse(sess *provisionersdk.Session, _ *proto.ParseRequest, _ <-chan struct{}) *proto.ParseComplete { + ctx := sess.Context() + _, span := s.startTrace(ctx, tracing.FuncName()) defer span.End() // Load the module and print any parse errors. - module, diags := tfconfig.LoadModule(request.Directory) + module, diags := tfconfig.LoadModule(sess.WorkDirectory) if diags.HasErrors() { - return xerrors.Errorf("load module: %s", formatDiagnostics(request.Directory, diags)) + return provisionersdk.ParseErrorf("load module: %s", formatDiagnostics(sess.WorkDirectory, diags)) } // Sort variables by (filename, line) to make the ordering consistent @@ -40,17 +42,13 @@ func (s *server) Parse(request *proto.Parse_Request, stream proto.DRPCProvisione for _, v := range variables { mv, err := convertTerraformVariable(v) if err != nil { - return xerrors.Errorf("can't convert the Terraform variable to a managed one: %w", err) + return provisionersdk.ParseErrorf("can't convert the Terraform variable to a managed one: %s", err) } templateVariables = append(templateVariables, mv) } - return stream.Send(&proto.Parse_Response{ - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{ - TemplateVariables: templateVariables, - }, - }, - }) + return &proto.ParseComplete{ + TemplateVariables: templateVariables, + } } // Converts a Terraform variable to a template-wide variable, processed by Coder. diff --git a/provisioner/terraform/parse_test.go b/provisioner/terraform/parse_test.go index aa0e19984b224..c28532af25831 100644 --- a/provisioner/terraform/parse_test.go +++ b/provisioner/terraform/parse_test.go @@ -4,8 +4,6 @@ package terraform_test import ( "encoding/json" - "os" - "path/filepath" "testing" "github.com/stretchr/testify/require" @@ -21,9 +19,8 @@ func TestParse(t *testing.T) { testCases := []struct { Name string Files map[string]string - Response *proto.Parse_Response - // If ErrorContains is not empty, then response.Recv() should return an - // error containing this string before a Complete response is returned. + Response *proto.ParseComplete + // If ErrorContains is not empty, then the ParseComplete should have an Error containing the given string ErrorContains string }{ { @@ -33,16 +30,12 @@ func TestParse(t *testing.T) { description = "Testing!" }`, }, - Response: &proto.Parse_Response{ - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{ - TemplateVariables: []*proto.TemplateVariable{ - { - Name: "A", - Description: "Testing!", - Required: true, - }, - }, + Response: &proto.ParseComplete{ + TemplateVariables: []*proto.TemplateVariable{ + { + Name: "A", + Description: "Testing!", + Required: true, }, }, }, @@ -54,15 +47,11 @@ func TestParse(t *testing.T) { default = "wow" }`, }, - Response: &proto.Parse_Response{ - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{ - TemplateVariables: []*proto.TemplateVariable{ - { - Name: "A", - DefaultValue: "wow", - }, - }, + Response: &proto.ParseComplete{ + TemplateVariables: []*proto.TemplateVariable{ + { + Name: "A", + DefaultValue: "wow", }, }, }, @@ -76,15 +65,11 @@ func TestParse(t *testing.T) { } }`, }, - Response: &proto.Parse_Response{ - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{ - TemplateVariables: []*proto.TemplateVariable{ - { - Name: "A", - Required: true, - }, - }, + Response: &proto.ParseComplete{ + TemplateVariables: []*proto.TemplateVariable{ + { + Name: "A", + Required: true, }, }, }, @@ -104,27 +89,23 @@ func TestParse(t *testing.T) { "main2.tf": `variable "baz" { } variable "quux" { }`, }, - Response: &proto.Parse_Response{ - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{ - TemplateVariables: []*proto.TemplateVariable{ - { - Name: "foo", - Required: true, - }, - { - Name: "bar", - Required: true, - }, - { - Name: "baz", - Required: true, - }, - { - Name: "quux", - Required: true, - }, - }, + Response: &proto.ParseComplete{ + TemplateVariables: []*proto.TemplateVariable{ + { + Name: "foo", + Required: true, + }, + { + Name: "bar", + Required: true, + }, + { + Name: "baz", + Required: true, + }, + { + Name: "quux", + Required: true, }, }, }, @@ -139,19 +120,15 @@ func TestParse(t *testing.T) { sensitive = true }`, }, - Response: &proto.Parse_Response{ - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{ - TemplateVariables: []*proto.TemplateVariable{ - { - Name: "A", - Description: "Testing!", - Type: "bool", - DefaultValue: "true", - Required: false, - Sensitive: true, - }, - }, + Response: &proto.ParseComplete{ + TemplateVariables: []*proto.TemplateVariable{ + { + Name: "A", + Description: "Testing!", + Type: "bool", + DefaultValue: "true", + Required: false, + Sensitive: true, }, }, }, @@ -166,19 +143,15 @@ func TestParse(t *testing.T) { sensitive = true }`, }, - Response: &proto.Parse_Response{ - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{ - TemplateVariables: []*proto.TemplateVariable{ - { - Name: "A", - Description: "Testing!", - Type: "string", - DefaultValue: "abc", - Required: false, - Sensitive: true, - }, - }, + Response: &proto.ParseComplete{ + TemplateVariables: []*proto.TemplateVariable{ + { + Name: "A", + Description: "Testing!", + Type: "string", + DefaultValue: "abc", + Required: false, + Sensitive: true, }, }, }, @@ -193,19 +166,15 @@ func TestParse(t *testing.T) { sensitive = true }`, }, - Response: &proto.Parse_Response{ - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{ - TemplateVariables: []*proto.TemplateVariable{ - { - Name: "A", - Description: "Testing!", - Type: "string", - DefaultValue: "", - Required: false, - Sensitive: true, - }, - }, + Response: &proto.ParseComplete{ + TemplateVariables: []*proto.TemplateVariable{ + { + Name: "A", + Description: "Testing!", + Type: "string", + DefaultValue: "", + Required: false, + Sensitive: true, }, }, }, @@ -219,19 +188,15 @@ func TestParse(t *testing.T) { sensitive = true }`, }, - Response: &proto.Parse_Response{ - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{ - TemplateVariables: []*proto.TemplateVariable{ - { - Name: "A", - Description: "Testing!", - Type: "string", - DefaultValue: "", - Required: true, - Sensitive: true, - }, - }, + Response: &proto.ParseComplete{ + TemplateVariables: []*proto.TemplateVariable{ + { + Name: "A", + Description: "Testing!", + Type: "string", + DefaultValue: "", + Required: true, + Sensitive: true, }, }, }, @@ -243,40 +208,31 @@ func TestParse(t *testing.T) { t.Run(testCase.Name, func(t *testing.T) { t.Parallel() - // Write all files to the temporary test directory. - directory := t.TempDir() - for path, content := range testCase.Files { - err := os.WriteFile(filepath.Join(directory, path), []byte(content), 0o600) - require.NoError(t, err) - } - - response, err := api.Parse(ctx, &proto.Parse_Request{ - Directory: directory, + session := configure(ctx, t, api, &proto.Config{ + TemplateSourceArchive: makeTar(t, testCase.Files), }) + + err := session.Send(&proto.Request{Type: &proto.Request_Parse{Parse: &proto.ParseRequest{}}}) require.NoError(t, err) for { - msg, err := response.Recv() - if err != nil { - if testCase.ErrorContains != "" { - require.ErrorContains(t, err, testCase.ErrorContains) - break - } + msg, err := session.Recv() + require.NoError(t, err) - require.NoError(t, err) + if testCase.ErrorContains != "" { + require.Contains(t, msg.GetParse().GetError(), testCase.ErrorContains) + break } - if msg.GetComplete() == nil { + // Ignore logs in this test + if msg.GetLog() != nil { continue } - if testCase.ErrorContains != "" { - t.Fatal("expected error but job completed successfully") - } // Ensure the want and got are equivalent! want, err := json.Marshal(testCase.Response) require.NoError(t, err) - got, err := json.Marshal(msg) + got, err := json.Marshal(msg.GetParse()) require.NoError(t, err) require.Equal(t, string(want), string(got)) diff --git a/provisioner/terraform/provision.go b/provisioner/terraform/provision.go index 504984520d3f2..f7d2d6f2326b2 100644 --- a/provisioner/terraform/provision.go +++ b/provisioner/terraform/provision.go @@ -1,63 +1,36 @@ package terraform import ( + "cdr.dev/slog" "context" "fmt" "os" - "path/filepath" "strings" "time" - "golang.org/x/xerrors" - "github.com/coder/coder/v2/coderd/tracing" "github.com/coder/coder/v2/provisionersdk" "github.com/coder/coder/v2/provisionersdk/proto" "github.com/coder/terraform-provider-coder/provider" ) -// Provision executes `terraform apply` or `terraform plan` for dry runs. -func (s *server) Provision(stream proto.DRPCProvisioner_ProvisionStream) error { - ctx, span := s.startTrace(stream.Context(), tracing.FuncName()) - defer span.End() - - request, err := stream.Recv() - if err != nil { - return err - } - if request.GetCancel() != nil { - return nil - } - - var ( - applyRequest = request.GetApply() - planRequest = request.GetPlan() - ) - - var config *proto.Provision_Config - if applyRequest == nil && planRequest == nil { - return nil - } else if applyRequest != nil { - config = applyRequest.Config - } else if planRequest != nil { - config = planRequest.Config - } - - // Create a context for graceful cancellation bound to the stream +func (s *server) setupContexts(parent context.Context, canceledOrComplete <-chan struct{}) ( + ctx context.Context, cancel func(), killCtx context.Context, kill func(), +) { + // Create a context for graceful cancellation bound to the session // context. This ensures that we will perform graceful cancellation // even on connection loss. - ctx, cancel := context.WithCancel(ctx) - defer cancel() + ctx, cancel = context.WithCancel(parent) // Create a separate context for forceful cancellation not tied to // the stream so that we can control when to terminate the process. - killCtx, kill := context.WithCancel(context.Background()) - defer kill() + killCtx, kill = context.WithCancel(context.Background()) // Ensure processes are eventually cleaned up on graceful // cancellation or disconnect. go func() { <-ctx.Done() + s.logger.Debug(ctx, "graceful context done") // TODO(mafredri): We should track this provision request as // part of graceful server shutdown procedure. Waiting on a @@ -66,134 +39,131 @@ func (s *server) Provision(stream proto.DRPCProvisioner_ProvisionStream) error { defer t.Stop() select { case <-t.C: + s.logger.Debug(ctx, "exit timeout hit") kill() case <-killCtx.Done(): + s.logger.Debug(ctx, "kill context done") } }() + // Process cancel go func() { - for { - request, err := stream.Recv() - if err != nil { - return - } - if request.GetCancel() == nil { - // We only process cancellation requests here. - continue - } - cancel() - return - } + <-canceledOrComplete + s.logger.Debug(ctx, "canceledOrComplete closed") + cancel() }() + return ctx, cancel, killCtx, kill +} - sink := streamLogSink{ - logger: s.logger.Named("execution_logs"), - stream: stream, - } - - e := s.executor(config.Directory) - if err = e.checkMinVersion(ctx); err != nil { - return err - } - logTerraformEnvVars(sink) +func (s *server) Plan( + sess *provisionersdk.Session, request *proto.PlanRequest, canceledOrComplete <-chan struct{}, +) *proto.PlanComplete { + ctx, span := s.startTrace(sess.Context(), tracing.FuncName()) + defer span.End() + ctx, cancel, killCtx, kill := s.setupContexts(ctx, canceledOrComplete) + defer cancel() + defer kill() - statefilePath := filepath.Join(config.Directory, "terraform.tfstate") - if len(config.State) > 0 { - err = os.WriteFile(statefilePath, config.State, 0o600) - if err != nil { - return xerrors.Errorf("write statefile %q: %w", statefilePath, err) - } + e := s.executor(sess.WorkDirectory) + if err := e.checkMinVersion(ctx); err != nil { + return provisionersdk.PlanErrorf(err.Error()) } + logTerraformEnvVars(sess) // If we're destroying, exit early if there's no state. This is necessary to // avoid any cases where a workspace is "locked out" of terraform due to // e.g. bad template param values and cannot be deleted. This is just for // contingency, in the future we will try harder to prevent workspaces being // broken this hard. - if config.Metadata.WorkspaceTransition == proto.WorkspaceTransition_DESTROY && len(config.State) == 0 { - _ = stream.Send(&proto.Provision_Response{ - Type: &proto.Provision_Response_Log{ - Log: &proto.Log{ - Level: proto.LogLevel_INFO, - Output: "The terraform state does not exist, there is nothing to do", - }, - }, - }) + if request.Metadata.GetWorkspaceTransition() == proto.WorkspaceTransition_DESTROY && len(sess.Config.State) == 0 { + sess.ProvisionLog(proto.LogLevel_INFO, "The terraform state does not exist, there is nothing to do") + return &proto.PlanComplete{} + } - return stream.Send(&proto.Provision_Response{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, - }, - }) + statefilePath := getStateFilePath(sess.WorkDirectory) + if len(sess.Config.State) > 0 { + err := os.WriteFile(statefilePath, sess.Config.State, 0o600) + if err != nil { + return provisionersdk.PlanErrorf("write statefile %q: %s", statefilePath, err) + } } s.logger.Debug(ctx, "running initialization") - err = e.init(ctx, killCtx, sink) + err := e.init(ctx, killCtx, sess) if err != nil { - if ctx.Err() != nil { - return stream.Send(&proto.Provision_Response{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Error: err.Error(), - }, - }, - }) - } - return xerrors.Errorf("initialize terraform: %w", err) + s.logger.Debug(ctx, "init failed", slog.Error(err)) + return provisionersdk.PlanErrorf("initialize terraform: %s", err) } s.logger.Debug(ctx, "ran initialization") - env, err := provisionEnv(config, request.GetPlan().GetRichParameterValues(), request.GetPlan().GetGitAuthProviders()) + + env, err := provisionEnv(sess.Config, request.Metadata, request.RichParameterValues, request.GitAuthProviders) if err != nil { - return err + return provisionersdk.PlanErrorf("setup env: %s", err) } - var resp *proto.Provision_Response - if planRequest != nil { - vars, err := planVars(planRequest) - if err != nil { - return err - } + vars, err := planVars(request) + if err != nil { + return provisionersdk.PlanErrorf("plan vars: %s", err) + } - resp, err = e.plan( - ctx, killCtx, env, vars, sink, - config.Metadata.WorkspaceTransition == proto.WorkspaceTransition_DESTROY, - ) - if err != nil { - if ctx.Err() != nil { - return stream.Send(&proto.Provision_Response{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Error: err.Error(), - }, - }, - }) - } - return xerrors.Errorf("plan terraform: %w", err) - } - return stream.Send(resp) + resp, err := e.plan( + ctx, killCtx, env, vars, sess, + request.Metadata.GetWorkspaceTransition() == proto.WorkspaceTransition_DESTROY, + ) + if err != nil { + return provisionersdk.PlanErrorf(err.Error()) + } + return resp +} + +func (s *server) Apply( + sess *provisionersdk.Session, request *proto.ApplyRequest, canceledOrComplete <-chan struct{}, +) *proto.ApplyComplete { + ctx, span := s.startTrace(sess.Context(), tracing.FuncName()) + defer span.End() + ctx, cancel, killCtx, kill := s.setupContexts(ctx, canceledOrComplete) + defer cancel() + defer kill() + + e := s.executor(sess.WorkDirectory) + if err := e.checkMinVersion(ctx); err != nil { + return provisionersdk.ApplyErrorf(err.Error()) + } + logTerraformEnvVars(sess) + + // Exit early if there is no plan file. This is necessary to + // avoid any cases where a workspace is "locked out" of terraform due to + // e.g. bad template param values and cannot be deleted. This is just for + // contingency, in the future we will try harder to prevent workspaces being + // broken this hard. + if request.Metadata.GetWorkspaceTransition() == proto.WorkspaceTransition_DESTROY && len(sess.Config.State) == 0 { + sess.ProvisionLog(proto.LogLevel_INFO, "The terraform plan does not exist, there is nothing to do") + return &proto.ApplyComplete{} } - // Must be apply - resp, err = e.apply( - ctx, killCtx, applyRequest.Plan, env, sink, + + // Earlier in the session, Plan() will have written the state file and the plan file. + statefilePath := getStateFilePath(sess.WorkDirectory) + env, err := provisionEnv(sess.Config, request.Metadata, nil, nil) + if err != nil { + return provisionersdk.ApplyErrorf("provision env: %s", err) + } + resp, err := e.apply( + ctx, killCtx, env, sess, ) if err != nil { errorMessage := err.Error() // Terraform can fail and apply and still need to store it's state. // In this case, we return Complete with an explicit error message. stateData, _ := os.ReadFile(statefilePath) - return stream.Send(&proto.Provision_Response{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - State: stateData, - Error: errorMessage, - }, - }, - }) + return &proto.ApplyComplete{ + State: stateData, + Error: errorMessage, + } } - return stream.Send(resp) + return resp } -func planVars(plan *proto.Provision_Plan) ([]string, error) { +func planVars(plan *proto.PlanRequest) ([]string, error) { vars := []string{} for _, variable := range plan.VariableValues { vars = append(vars, fmt.Sprintf("%s=%s", variable.Name, variable.Value)) @@ -201,18 +171,21 @@ func planVars(plan *proto.Provision_Plan) ([]string, error) { return vars, nil } -func provisionEnv(config *proto.Provision_Config, richParams []*proto.RichParameterValue, gitAuth []*proto.GitAuthProvider) ([]string, error) { +func provisionEnv( + config *proto.Config, metadata *proto.Metadata, + richParams []*proto.RichParameterValue, gitAuth []*proto.GitAuthProvider, +) ([]string, error) { env := safeEnviron() env = append(env, - "CODER_AGENT_URL="+config.Metadata.CoderUrl, - "CODER_WORKSPACE_TRANSITION="+strings.ToLower(config.Metadata.WorkspaceTransition.String()), - "CODER_WORKSPACE_NAME="+config.Metadata.WorkspaceName, - "CODER_WORKSPACE_OWNER="+config.Metadata.WorkspaceOwner, - "CODER_WORKSPACE_OWNER_EMAIL="+config.Metadata.WorkspaceOwnerEmail, - "CODER_WORKSPACE_OWNER_OIDC_ACCESS_TOKEN="+config.Metadata.WorkspaceOwnerOidcAccessToken, - "CODER_WORKSPACE_ID="+config.Metadata.WorkspaceId, - "CODER_WORKSPACE_OWNER_ID="+config.Metadata.WorkspaceOwnerId, - "CODER_WORKSPACE_OWNER_SESSION_TOKEN="+config.Metadata.WorkspaceOwnerSessionToken, + "CODER_AGENT_URL="+metadata.GetCoderUrl(), + "CODER_WORKSPACE_TRANSITION="+strings.ToLower(metadata.GetWorkspaceTransition().String()), + "CODER_WORKSPACE_NAME="+metadata.GetWorkspaceName(), + "CODER_WORKSPACE_OWNER="+metadata.GetWorkspaceOwner(), + "CODER_WORKSPACE_OWNER_EMAIL="+metadata.GetWorkspaceOwnerEmail(), + "CODER_WORKSPACE_OWNER_OIDC_ACCESS_TOKEN="+metadata.GetWorkspaceOwnerOidcAccessToken(), + "CODER_WORKSPACE_ID="+metadata.GetWorkspaceId(), + "CODER_WORKSPACE_OWNER_ID="+metadata.GetWorkspaceOwnerId(), + "CODER_WORKSPACE_OWNER_SESSION_TOKEN="+metadata.GetWorkspaceOwnerSessionToken(), ) for key, value := range provisionersdk.AgentScriptEnv() { env = append(env, key+"="+value) @@ -258,10 +231,10 @@ func logTerraformEnvVars(sink logSink) { if !tfEnvSafeToPrint[parts[0]] { parts[1] = "" } - sink.Log(&proto.Log{ - Level: proto.LogLevel_WARN, - Output: fmt.Sprintf("terraform environment variable: %s=%s", parts[0], parts[1]), - }) + sink.ProvisionLog( + proto.LogLevel_WARN, + fmt.Sprintf("terraform environment variable: %s=%s", parts[0], parts[1]), + ) } } } diff --git a/provisioner/terraform/provision_test.go b/provisioner/terraform/provision_test.go index 03fc70ed696c5..9fa56309a6f5a 100644 --- a/provisioner/terraform/provision_test.go +++ b/provisioner/terraform/provision_test.go @@ -3,6 +3,8 @@ package terraform_test import ( + "archive/tar" + "bytes" "context" "encoding/json" "errors" @@ -35,6 +37,7 @@ func setupProvisioner(t *testing.T, opts *provisionerServeOptions) (context.Cont opts = &provisionerServeOptions{} } cachePath := t.TempDir() + workDir := t.TempDir() client, server := provisionersdk.MemTransportPipe() ctx, cancelFunc := context.WithCancel(context.Background()) serverErr := make(chan error, 1) @@ -50,25 +53,51 @@ func setupProvisioner(t *testing.T, opts *provisionerServeOptions) (context.Cont go func() { serverErr <- terraform.Serve(ctx, &terraform.ServeOptions{ ServeOptions: &provisionersdk.ServeOptions{ - Listener: server, + Listener: server, + Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug), + WorkDirectory: workDir, }, BinaryPath: opts.binaryPath, CachePath: cachePath, - Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug), ExitTimeout: opts.exitTimeout, }) }() api := proto.NewDRPCProvisionerClient(client) + return ctx, api } -func readProvisionLog(t *testing.T, response proto.DRPCProvisioner_ProvisionClient) ( - string, - *proto.Provision_Complete, -) { +func makeTar(t *testing.T, files map[string]string) []byte { + t.Helper() + var buffer bytes.Buffer + writer := tar.NewWriter(&buffer) + for name, content := range files { + err := writer.WriteHeader(&tar.Header{ + Name: name, + Size: int64(len(content)), + Mode: 0o644, + }) + require.NoError(t, err) + _, err = writer.Write([]byte(content)) + require.NoError(t, err) + } + err := writer.Flush() + require.NoError(t, err) + return buffer.Bytes() +} + +func configure(ctx context.Context, t *testing.T, client proto.DRPCProvisionerClient, config *proto.Config) proto.DRPCProvisioner_SessionClient { + t.Helper() + sess, err := client.Session(ctx) + require.NoError(t, err) + err = sess.Send(&proto.Request{Type: &proto.Request_Config{Config: config}}) + require.NoError(t, err) + return sess +} + +func readProvisionLog(t *testing.T, response proto.DRPCProvisioner_SessionClient) string { var ( logBuf strings.Builder - c *proto.Provision_Complete ) for { msg, err := response.Recv() @@ -76,14 +105,25 @@ func readProvisionLog(t *testing.T, response proto.DRPCProvisioner_ProvisionClie if log := msg.GetLog(); log != nil { t.Log(log.Level.String(), log.Output) - _, _ = logBuf.WriteString(log.Output) - } - if c = msg.GetComplete(); c != nil { - require.Empty(t, c.Error) - break + _, err = logBuf.WriteString(log.Output) + require.NoError(t, err) + continue } + break } - return logBuf.String(), c + return logBuf.String() +} + +func sendPlan(sess proto.DRPCProvisioner_SessionClient, transition proto.WorkspaceTransition) error { + return sess.Send(&proto.Request{Type: &proto.Request_Plan{Plan: &proto.PlanRequest{ + Metadata: &proto.Metadata{WorkspaceTransition: transition}, + }}}) +} + +func sendApply(sess proto.DRPCProvisioner_SessionClient, transition proto.WorkspaceTransition) error { + return sess.Send(&proto.Request{Type: &proto.Request_Apply{Apply: &proto.ApplyRequest{ + Metadata: &proto.Metadata{WorkspaceTransition: transition}, + }}}) } func TestProvision_Cancel(t *testing.T) { @@ -109,9 +149,10 @@ func TestProvision_Cancel(t *testing.T) { wantLog: []string{"interrupt", "exit"}, }, { - name: "Cancel apply", - mode: "apply", - startSequence: []string{"init", "apply_start"}, + // Provisioner requires a plan before an apply, so test cancel with plan. + name: "Cancel plan", + mode: "plan", + startSequence: []string{"init", "plan_start"}, wantLog: []string{"interrupt", "exit"}, }, } @@ -131,24 +172,16 @@ func TestProvision_Cancel(t *testing.T) { ctx, api := setupProvisioner(t, &provisionerServeOptions{ binaryPath: binPath, }) - - response, err := api.Provision(ctx) - require.NoError(t, err) - err = response.Send(&proto.Provision_Request{ - Type: &proto.Provision_Request_Apply{ - Apply: &proto.Provision_Apply{ - Config: &proto.Provision_Config{ - Directory: dir, - Metadata: &proto.Provision_Metadata{}, - }, - }, - }, + sess := configure(ctx, t, api, &proto.Config{ + TemplateSourceArchive: makeTar(t, nil), }) + + err = sendPlan(sess, proto.WorkspaceTransition_START) require.NoError(t, err) for _, line := range tt.startSequence { LoopStart: - msg, err := response.Recv() + msg, err := sess.Recv() require.NoError(t, err) t.Log(msg.Type) @@ -160,22 +193,22 @@ func TestProvision_Cancel(t *testing.T) { require.Equal(t, line, log.Output) } - err = response.Send(&proto.Provision_Request{ - Type: &proto.Provision_Request_Cancel{ - Cancel: &proto.Provision_Cancel{}, + err = sess.Send(&proto.Request{ + Type: &proto.Request_Cancel{ + Cancel: &proto.CancelRequest{}, }, }) require.NoError(t, err) var gotLog []string for { - msg, err := response.Recv() + msg, err := sess.Recv() require.NoError(t, err) if log := msg.GetLog(); log != nil { gotLog = append(gotLog, log.Output) } - if c := msg.GetComplete(); c != nil { + if c := msg.GetPlan(); c != nil { require.Contains(t, c.Error, "exit status 1") break } @@ -208,23 +241,17 @@ func TestProvision_CancelTimeout(t *testing.T) { exitTimeout: time.Second, }) - response, err := api.Provision(ctx) - require.NoError(t, err) - err = response.Send(&proto.Provision_Request{ - Type: &proto.Provision_Request_Apply{ - Apply: &proto.Provision_Apply{ - Config: &proto.Provision_Config{ - Directory: dir, - Metadata: &proto.Provision_Metadata{}, - }, - }, - }, + sess := configure(ctx, t, api, &proto.Config{ + TemplateSourceArchive: makeTar(t, nil), }) + + // provisioner requires plan before apply, so test cancel with plan. + err = sendPlan(sess, proto.WorkspaceTransition_START) require.NoError(t, err) - for _, line := range []string{"init", "apply_start"} { + for _, line := range []string{"init", "plan_start"} { LoopStart: - msg, err := response.Recv() + msg, err := sess.Recv() require.NoError(t, err) t.Log(msg.Type) @@ -236,18 +263,14 @@ func TestProvision_CancelTimeout(t *testing.T) { require.Equal(t, line, log.Output) } - err = response.Send(&proto.Provision_Request{ - Type: &proto.Provision_Request_Cancel{ - Cancel: &proto.Provision_Cancel{}, - }, - }) + err = sess.Send(&proto.Request{Type: &proto.Request_Cancel{Cancel: &proto.CancelRequest{}}}) require.NoError(t, err) for { - msg, err := response.Recv() + msg, err := sess.Recv() require.NoError(t, err) - if c := msg.GetComplete(); c != nil { + if c := msg.GetPlan(); c != nil { require.Contains(t, c.Error, "killed") break } @@ -258,17 +281,18 @@ func TestProvision(t *testing.T) { t.Parallel() testCases := []struct { - Name string - Files map[string]string - Request *proto.Provision_Plan + Name string + Files map[string]string + Metadata *proto.Metadata + Request *proto.PlanRequest // Response may be nil to not check the response. - Response *proto.Provision_Response - // If ErrorContains is not empty, then response.Recv() should return an - // error containing this string before a Complete response is returned. + Response *proto.PlanComplete + // If ErrorContains is not empty, PlanComplete should have an Error containing the given string ErrorContains string // If ExpectLogContains is not empty, then the logs should contain it. ExpectLogContains string - Apply bool + // If Apply is true, then send an Apply request and check we get the same Resources as in Response. + Apply bool }{ { Name: "missing-variable", @@ -293,15 +317,11 @@ func TestProvision(t *testing.T) { Files: map[string]string{ "main.tf": `resource "null_resource" "A" {}`, }, - Response: &proto.Provision_Response{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Resources: []*proto.Resource{{ - Name: "A", - Type: "null_resource", - }}, - }, - }, + Response: &proto.PlanComplete{ + Resources: []*proto.Resource{{ + Name: "A", + Type: "null_resource", + }}, }, }, { @@ -309,15 +329,11 @@ func TestProvision(t *testing.T) { Files: map[string]string{ "main.tf": `resource "null_resource" "A" {}`, }, - Response: &proto.Provision_Response{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Resources: []*proto.Resource{{ - Name: "A", - Type: "null_resource", - }}, - }, - }, + Response: &proto.PlanComplete{ + Resources: []*proto.Resource{{ + Name: "A", + Type: "null_resource", + }}, }, Apply: true, }, @@ -334,15 +350,11 @@ func TestProvision(t *testing.T) { } }`, }, - Response: &proto.Provision_Response{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Resources: []*proto.Resource{{ - Name: "A", - Type: "null_resource", - }}, - }, - }, + Response: &proto.PlanComplete{ + Resources: []*proto.Resource{{ + Name: "A", + Type: "null_resource", + }}, }, Apply: true, }, @@ -367,12 +379,8 @@ func TestProvision(t *testing.T) { Files: map[string]string{ "main.tf": `resource "null_resource" "A" {}`, }, - Request: &proto.Provision_Plan{ - Config: &proto.Provision_Config{ - Metadata: &proto.Provision_Metadata{ - WorkspaceTransition: proto.WorkspaceTransition_DESTROY, - }, - }, + Metadata: &proto.Metadata{ + WorkspaceTransition: proto.WorkspaceTransition_DESTROY, }, ExpectLogContains: "nothing to do", }, @@ -406,7 +414,7 @@ func TestProvision(t *testing.T) { } }`, }, - Request: &proto.Provision_Plan{ + Request: &proto.PlanRequest{ RichParameterValues: []*proto.RichParameterValue{ { Name: "Example", @@ -418,27 +426,23 @@ func TestProvision(t *testing.T) { }, }, }, - Response: &proto.Provision_Response{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Parameters: []*proto.RichParameter{ - { - Name: "Example", - Type: "string", - DefaultValue: "foobar", - }, - { - Name: "Sample", - Type: "string", - DefaultValue: "foobaz", - }, - }, - Resources: []*proto.Resource{{ - Name: "example", - Type: "null_resource", - }}, + Response: &proto.PlanComplete{ + Parameters: []*proto.RichParameter{ + { + Name: "Example", + Type: "string", + DefaultValue: "foobar", + }, + { + Name: "Sample", + Type: "string", + DefaultValue: "foobaz", }, }, + Resources: []*proto.Resource{{ + Name: "example", + Type: "null_resource", + }}, }, }, { @@ -488,7 +492,7 @@ func TestProvision(t *testing.T) { ] }`, }, - Request: &proto.Provision_Plan{ + Request: &proto.PlanRequest{ RichParameterValues: []*proto.RichParameterValue{ { Name: "Example", @@ -500,27 +504,23 @@ func TestProvision(t *testing.T) { }, }, }, - Response: &proto.Provision_Response{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Parameters: []*proto.RichParameter{ - { - Name: "Example", - Type: "string", - DefaultValue: "foobar", - }, - { - Name: "Sample", - Type: "string", - DefaultValue: "foobaz", - }, - }, - Resources: []*proto.Resource{{ - Name: "example", - Type: "null_resource", - }}, + Response: &proto.PlanComplete{ + Parameters: []*proto.RichParameter{ + { + Name: "Example", + Type: "string", + DefaultValue: "foobar", + }, + { + Name: "Sample", + Type: "string", + DefaultValue: "foobaz", }, }, + Resources: []*proto.Resource{{ + Name: "example", + Type: "null_resource", + }}, }, }, { @@ -550,25 +550,21 @@ func TestProvision(t *testing.T) { } `, }, - Request: &proto.Provision_Plan{ + Request: &proto.PlanRequest{ GitAuthProviders: []*proto.GitAuthProvider{{ Id: "github", AccessToken: "some-value", }}, }, - Response: &proto.Provision_Response{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Resources: []*proto.Resource{{ - Name: "example", - Type: "null_resource", - Metadata: []*proto.Resource_Metadata{{ - Key: "token", - Value: "some-value", - }}, - }}, - }, - }, + Response: &proto.PlanComplete{ + Resources: []*proto.Resource{{ + Name: "example", + Type: "null_resource", + Metadata: []*proto.Resource_Metadata{{ + Key: "token", + Value: "some-value", + }}, + }}, }, }, } @@ -579,50 +575,26 @@ func TestProvision(t *testing.T) { t.Parallel() ctx, api := setupProvisioner(t, nil) + sess := configure(ctx, t, api, &proto.Config{ + TemplateSourceArchive: makeTar(t, testCase.Files), + }) - directory := t.TempDir() - for path, content := range testCase.Files { - err := os.WriteFile(filepath.Join(directory, path), []byte(content), 0o600) - require.NoError(t, err) - } - - planRequest := &proto.Provision_Request{ - Type: &proto.Provision_Request_Plan{ - Plan: &proto.Provision_Plan{ - Config: &proto.Provision_Config{ - Directory: directory, - }, - }, - }, - } + planRequest := &proto.Request{Type: &proto.Request_Plan{Plan: &proto.PlanRequest{ + Metadata: testCase.Metadata, + }}} if testCase.Request != nil { - if planRequest.GetPlan().GetConfig() == nil { - planRequest.GetPlan().Config = &proto.Provision_Config{} - } - planRequest.GetPlan().RichParameterValues = testCase.Request.RichParameterValues - planRequest.GetPlan().GitAuthProviders = testCase.Request.GitAuthProviders - if testCase.Request.Config != nil { - planRequest.GetPlan().Config.State = testCase.Request.Config.State - planRequest.GetPlan().Config.Metadata = testCase.Request.Config.Metadata - } - } - if planRequest.GetPlan().Config.Metadata == nil { - planRequest.GetPlan().Config.Metadata = &proto.Provision_Metadata{} + planRequest = &proto.Request{Type: &proto.Request_Plan{Plan: testCase.Request}} } gotExpectedLog := testCase.ExpectLogContains == "" - provision := func(req *proto.Provision_Request) *proto.Provision_Complete { - response, err := api.Provision(ctx) + provision := func(req *proto.Request) *proto.Response { + err := sess.Send(req) require.NoError(t, err) - err = response.Send(req) - require.NoError(t, err) - - var complete *proto.Provision_Complete - for { - msg, err := response.Recv() - if msg != nil && msg.GetLog() != nil { + msg, err := sess.Recv() + require.NoError(t, err) + if msg.GetLog() != nil { if testCase.ExpectLogContains != "" && strings.Contains(msg.GetLog().Output, testCase.ExpectLogContains) { gotExpectedLog = true } @@ -630,67 +602,52 @@ func TestProvision(t *testing.T) { t.Logf("log: [%s] %s", msg.GetLog().Level, msg.GetLog().Output) continue } - if testCase.ErrorContains != "" { - require.ErrorContains(t, err, testCase.ErrorContains) - break - } - require.NoError(t, err) - - if complete = msg.GetComplete(); complete == nil { - continue - } - - require.NoError(t, err) - - // Remove randomly generated data. - for _, resource := range msg.GetComplete().Resources { - sort.Slice(resource.Agents, func(i, j int) bool { - return resource.Agents[i].Name < resource.Agents[j].Name - }) - - for _, agent := range resource.Agents { - agent.Id = "" - if agent.GetToken() == "" { - continue - } - agent.Auth = &proto.Agent_Token{} - } - } + return msg + } + } - if testCase.Response != nil { - require.Equal(t, testCase.Response.GetComplete().Error, msg.GetComplete().Error) + resp := provision(planRequest) + planComplete := resp.GetPlan() + require.NotNil(t, planComplete) - resourcesGot, err := json.Marshal(msg.GetComplete().Resources) - require.NoError(t, err) - resourcesWant, err := json.Marshal(testCase.Response.GetComplete().Resources) - require.NoError(t, err) + if testCase.ErrorContains != "" { + require.Contains(t, planComplete.GetError(), testCase.ErrorContains) + } - require.Equal(t, string(resourcesWant), string(resourcesGot)) + if testCase.Response != nil { + require.Equal(t, testCase.Response.Error, planComplete.Error) - parametersGot, err := json.Marshal(msg.GetComplete().Parameters) - require.NoError(t, err) - parametersWant, err := json.Marshal(testCase.Response.GetComplete().Parameters) - require.NoError(t, err) - require.Equal(t, string(parametersWant), string(parametersGot)) - } - break - } + // Remove randomly generated data. + normalizeResources(planComplete.Resources) + resourcesGot, err := json.Marshal(planComplete.Resources) + require.NoError(t, err) + resourcesWant, err := json.Marshal(testCase.Response.Resources) + require.NoError(t, err) + require.Equal(t, string(resourcesWant), string(resourcesGot)) - return complete + parametersGot, err := json.Marshal(planComplete.Parameters) + require.NoError(t, err) + parametersWant, err := json.Marshal(testCase.Response.Parameters) + require.NoError(t, err) + require.Equal(t, string(parametersWant), string(parametersGot)) } - planComplete := provision(planRequest) - if testCase.Apply { - require.NotNil(t, planComplete.Plan) - provision(&proto.Provision_Request{ - Type: &proto.Provision_Request_Apply{ - Apply: &proto.Provision_Apply{ - Config: planRequest.GetPlan().GetConfig(), - Plan: planComplete.Plan, - }, - }, - }) + resp = provision(&proto.Request{Type: &proto.Request_Apply{Apply: &proto.ApplyRequest{ + Metadata: &proto.Metadata{WorkspaceTransition: proto.WorkspaceTransition_START}, + }}}) + applyComplete := resp.GetApply() + require.NotNil(t, applyComplete) + + if testCase.Response != nil { + normalizeResources(applyComplete.Resources) + resourcesGot, err := json.Marshal(applyComplete.Resources) + require.NoError(t, err) + resourcesWant, err := json.Marshal(testCase.Response.Resources) + require.NoError(t, err) + require.Equal(t, string(resourcesWant), string(resourcesGot)) + } + } if !gotExpectedLog { @@ -700,6 +657,22 @@ func TestProvision(t *testing.T) { } } +func normalizeResources(resources []*proto.Resource) { + for _, resource := range resources { + sort.Slice(resource.Agents, func(i, j int) bool { + return resource.Agents[i].Name < resource.Agents[j].Name + }) + + for _, agent := range resource.Agents { + agent.Id = "" + if agent.GetToken() == "" { + continue + } + agent.Auth = &proto.Agent_Token{} + } + } +} + // nolint:paralleltest func TestProvision_ExtraEnv(t *testing.T) { // #nosec @@ -708,31 +681,15 @@ func TestProvision_ExtraEnv(t *testing.T) { t.Setenv("TF_SUPERSECRET", secretValue) ctx, api := setupProvisioner(t, nil) + sess := configure(ctx, t, api, &proto.Config{ + TemplateSourceArchive: makeTar(t, map[string]string{"main.tf": `resource "null_resource" "A" {}`}), + }) - directory := t.TempDir() - path := filepath.Join(directory, "main.tf") - err := os.WriteFile(path, []byte(`resource "null_resource" "A" {}`), 0o600) - require.NoError(t, err) - - request := &proto.Provision_Request{ - Type: &proto.Provision_Request_Plan{ - Plan: &proto.Provision_Plan{ - Config: &proto.Provision_Config{ - Directory: directory, - Metadata: &proto.Provision_Metadata{ - WorkspaceTransition: proto.WorkspaceTransition_START, - }, - }, - }, - }, - } - response, err := api.Provision(ctx) - require.NoError(t, err) - err = response.Send(request) + err := sendPlan(sess, proto.WorkspaceTransition_START) require.NoError(t, err) found := false for { - msg, err := response.Recv() + msg, err := sess.Recv() require.NoError(t, err) if log := msg.GetLog(); log != nil { @@ -742,7 +699,7 @@ func TestProvision_ExtraEnv(t *testing.T) { } require.NotContains(t, log.Output, secretValue) } - if c := msg.GetComplete(); c != nil { + if c := msg.GetPlan(); c != nil { require.Empty(t, c.Error) break } @@ -774,48 +731,19 @@ func TestProvision_SafeEnv(t *testing.T) { ` ctx, api := setupProvisioner(t, nil) - - directory := t.TempDir() - path := filepath.Join(directory, "main.tf") - err := os.WriteFile(path, []byte(echoResource), 0o600) - require.NoError(t, err) - - response, err := api.Provision(ctx) - require.NoError(t, err) - err = response.Send(&proto.Provision_Request{ - Type: &proto.Provision_Request_Plan{ - Plan: &proto.Provision_Plan{ - Config: &proto.Provision_Config{ - Directory: directory, - Metadata: &proto.Provision_Metadata{ - WorkspaceTransition: proto.WorkspaceTransition_START, - }, - }, - }, - }, + sess := configure(ctx, t, api, &proto.Config{ + TemplateSourceArchive: makeTar(t, map[string]string{"main.tf": echoResource}), }) + + err := sendPlan(sess, proto.WorkspaceTransition_START) require.NoError(t, err) - _, complete := readProvisionLog(t, response) + _ = readProvisionLog(t, sess) - response, err = api.Provision(ctx) - require.NoError(t, err) - err = response.Send(&proto.Provision_Request{ - Type: &proto.Provision_Request_Apply{ - Apply: &proto.Provision_Apply{ - Config: &proto.Provision_Config{ - Directory: directory, - Metadata: &proto.Provision_Metadata{ - WorkspaceTransition: proto.WorkspaceTransition_START, - }, - }, - Plan: complete.GetPlan(), - }, - }, - }) + err = sess.Send(&proto.Request{Type: &proto.Request_Apply{Apply: &proto.ApplyRequest{}}}) require.NoError(t, err) - log, _ := readProvisionLog(t, response) + log := readProvisionLog(t, sess) require.Contains(t, log, passedValue) require.NotContains(t, log, secretValue) require.Contains(t, log, "CODER_") diff --git a/provisioner/terraform/serve.go b/provisioner/terraform/serve.go index 7a25d27dca598..0fc12ea870896 100644 --- a/provisioner/terraform/serve.go +++ b/provisioner/terraform/serve.go @@ -24,7 +24,6 @@ type ServeOptions struct { BinaryPath string // CachePath must not be used by multiple processes at once. CachePath string - Logger slog.Logger Tracer trace.Tracer // ExitTimeout defines how long we will wait for a running Terraform @@ -128,5 +127,6 @@ func (s *server) executor(workdir string) *executor { binaryPath: s.binaryPath, cachePath: s.cachePath, workdir: workdir, + logger: s.logger.Named("executor"), } } diff --git a/provisioner/terraform/testdata/fake_cancel.sh b/provisioner/terraform/testdata/fake_cancel.sh index cd2511facf938..2ea713379cce9 100755 --- a/provisioner/terraform/testdata/fake_cancel.sh +++ b/provisioner/terraform/testdata/fake_cancel.sh @@ -22,8 +22,9 @@ version) ;; init) case "$MODE" in - apply) + plan) echo "init" + exit 0 ;; init) sleep 10 & @@ -39,7 +40,7 @@ init) ;; esac ;; -apply) +plan) sleep 10 & sleep_pid=$! @@ -47,14 +48,14 @@ apply) trap 'json_print interrupt; exit 1' INT trap 'json_print terminate; exit 2' TERM - json_print apply_start + json_print plan_start wait - json_print apply_end + json_print plan_end ;; -plan) - echo "plan not supported" +apply) + echo "apply not supported" exit 1 ;; esac -exit 0 +exit 10 diff --git a/provisioner/terraform/testdata/fake_cancel_hang.sh b/provisioner/terraform/testdata/fake_cancel_hang.sh index c6d29c88c733f..e8db67f6837cd 100755 --- a/provisioner/terraform/testdata/fake_cancel_hang.sh +++ b/provisioner/terraform/testdata/fake_cancel_hang.sh @@ -23,19 +23,19 @@ init) echo "init" exit 0 ;; -apply) +plan) trap 'json_print interrupt' INT - json_print apply_start + json_print plan_start sleep 10 2>/dev/null >/dev/null - json_print apply_end + json_print plan_end exit 0 ;; -plan) - echo "plan not supported" +apply) + echo "apply not supported" exit 1 ;; esac -exit 0 +exit 10 diff --git a/provisionersdk/errors.go b/provisionersdk/errors.go new file mode 100644 index 0000000000000..0dc66e6e6b301 --- /dev/null +++ b/provisionersdk/errors.go @@ -0,0 +1,19 @@ +package provisionersdk + +import ( + "fmt" + + "github.com/coder/coder/v2/provisionersdk/proto" +) + +func ParseErrorf(format string, args ...any) *proto.ParseComplete { + return &proto.ParseComplete{Error: fmt.Sprintf(format, args...)} +} + +func PlanErrorf(format string, args ...any) *proto.PlanComplete { + return &proto.PlanComplete{Error: fmt.Sprintf(format, args...)} +} + +func ApplyErrorf(format string, args ...any) *proto.ApplyComplete { + return &proto.ApplyComplete{Error: fmt.Sprintf(format, args...)} +} diff --git a/provisionersdk/serve.go b/provisionersdk/serve.go index ea3364b6054fe..924c7ad013982 100644 --- a/provisionersdk/serve.go +++ b/provisionersdk/serve.go @@ -13,6 +13,8 @@ import ( "storj.io/drpc/drpcmux" "storj.io/drpc/drpcserver" + "cdr.dev/slog" + "github.com/coder/coder/v2/coderd/tracing" "github.com/coder/coder/v2/provisionersdk/proto" ) @@ -20,11 +22,19 @@ import ( // ServeOptions are configurations to serve a provisioner. type ServeOptions struct { // Conn specifies a custom transport to serve the dRPC connection. - Listener net.Listener + Listener net.Listener + Logger slog.Logger + WorkDirectory string +} + +type Server interface { + Parse(s *Session, r *proto.ParseRequest, canceledOrComplete <-chan struct{}) *proto.ParseComplete + Plan(s *Session, r *proto.PlanRequest, canceledOrComplete <-chan struct{}) *proto.PlanComplete + Apply(s *Session, r *proto.ApplyRequest, canceledOrComplete <-chan struct{}) *proto.ApplyComplete } // Serve starts a dRPC connection for the provisioner and transport provided. -func Serve(ctx context.Context, server proto.DRPCProvisionerServer, options *ServeOptions) error { +func Serve(ctx context.Context, server Server, options *ServeOptions) error { if options == nil { options = &ServeOptions{} } @@ -45,11 +55,22 @@ func Serve(ctx context.Context, server proto.DRPCProvisionerServer, options *Ser }() options.Listener = stdio } + if options.WorkDirectory == "" { + var err error + options.WorkDirectory, err = os.MkdirTemp("", "coderprovisioner") + if err != nil { + return xerrors.Errorf("failed to init temp work dir: %w", err) + } + } // dRPC is a drop-in replacement for gRPC with less generated code, and faster transports. // See: https://www.storj.io/blog/introducing-drpc-our-replacement-for-grpc mux := drpcmux.New() - err := proto.DRPCRegisterProvisioner(mux, server) + ps := &protoServer{ + server: server, + opts: *options, + } + err := proto.DRPCRegisterProvisioner(mux, ps) if err != nil { return xerrors.Errorf("register provisioner: %w", err) } diff --git a/provisionersdk/serve_test.go b/provisionersdk/serve_test.go index dedf891889d8a..00cbbf19c8890 100644 --- a/provisionersdk/serve_test.go +++ b/provisionersdk/serve_test.go @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/goleak" - "storj.io/drpc/drpcerr" "github.com/coder/coder/v2/provisionersdk" "github.com/coder/coder/v2/provisionersdk/proto" @@ -28,17 +27,39 @@ func TestProvisionerSDK(t *testing.T) { ctx, cancelFunc := context.WithCancel(context.Background()) defer cancelFunc() go func() { - err := provisionersdk.Serve(ctx, &proto.DRPCProvisionerUnimplementedServer{}, &provisionersdk.ServeOptions{ - Listener: server, + err := provisionersdk.Serve(ctx, unimplementedServer{}, &provisionersdk.ServeOptions{ + Listener: server, + WorkDirectory: t.TempDir(), }) assert.NoError(t, err) }() api := proto.NewDRPCProvisionerClient(client) - stream, err := api.Parse(context.Background(), &proto.Parse_Request{}) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + s, err := api.Session(context.Background()) require.NoError(t, err) - _, err = stream.Recv() - require.Equal(t, drpcerr.Unimplemented, int(drpcerr.Code(err))) + err = s.Send(&proto.Request{Type: &proto.Request_Config{Config: &proto.Config{}}}) + require.NoError(t, err) + + err = s.Send(&proto.Request{Type: &proto.Request_Parse{Parse: &proto.ParseRequest{}}}) + require.NoError(t, err) + msg, err := s.Recv() + require.NoError(t, err) + require.Equal(t, "unimplemented", msg.GetParse().GetError()) + + err = s.Send(&proto.Request{Type: &proto.Request_Plan{Plan: &proto.PlanRequest{}}}) + require.NoError(t, err) + msg, err = s.Recv() + require.NoError(t, err) + // Plan has no error so that we're allowed to run Apply + require.Equal(t, "", msg.GetPlan().GetError()) + + err = s.Send(&proto.Request{Type: &proto.Request_Apply{Apply: &proto.ApplyRequest{}}}) + require.NoError(t, err) + msg, err = s.Recv() + require.NoError(t, err) + require.Equal(t, "unimplemented", msg.GetApply().GetError()) }) t.Run("ServeClosedPipe", func(t *testing.T) { @@ -47,9 +68,24 @@ func TestProvisionerSDK(t *testing.T) { _ = client.Close() _ = server.Close() - err := provisionersdk.Serve(context.Background(), &proto.DRPCProvisionerUnimplementedServer{}, &provisionersdk.ServeOptions{ - Listener: server, + err := provisionersdk.Serve(context.Background(), unimplementedServer{}, &provisionersdk.ServeOptions{ + Listener: server, + WorkDirectory: t.TempDir(), }) require.NoError(t, err) }) } + +type unimplementedServer struct{} + +func (_ unimplementedServer) Parse(_ *provisionersdk.Session, _ *proto.ParseRequest, _ <-chan struct{}) *proto.ParseComplete { + return &proto.ParseComplete{Error: "unimplemented"} +} + +func (_ unimplementedServer) Plan(_ *provisionersdk.Session, _ *proto.PlanRequest, _ <-chan struct{}) *proto.PlanComplete { + return &proto.PlanComplete{} +} + +func (_ unimplementedServer) Apply(_ *provisionersdk.Session, _ *proto.ApplyRequest, _ <-chan struct{}) *proto.ApplyComplete { + return &proto.ApplyComplete{Error: "unimplemented"} +} diff --git a/provisionersdk/session.go b/provisionersdk/session.go new file mode 100644 index 0000000000000..fa5e63e7b5ea6 --- /dev/null +++ b/provisionersdk/session.go @@ -0,0 +1,298 @@ +package provisionersdk + +import ( + "archive/tar" + "bytes" + "cdr.dev/slog" + "context" + "fmt" + "golang.org/x/xerrors" + "io" + "os" + "path/filepath" + "strings" + "time" + + "github.com/coder/coder/v2/provisionersdk/proto" +) + +// ReadmeFile is the location we look for to extract documentation from template +// versions. +const ReadmeFile = "README.md" + +// protoServer is a wrapper that translates the dRPC protocol into a Session with method calls into the Server. +type protoServer struct { + server Server + opts ServeOptions +} + +func (p *protoServer) Session(stream proto.DRPCProvisioner_SessionStream) error { + s := &Session{ + Logger: p.opts.Logger, + stream: stream, + server: p.server, + } + sessDir := fmt.Sprintf("Session%p", s) + s.WorkDirectory = filepath.Join(p.opts.WorkDirectory, sessDir) + err := os.MkdirAll(s.WorkDirectory, 0o700) + if err != nil { + return xerrors.Errorf("create work directory %q: %w", s.WorkDirectory, err) + } + defer func() { + // Cleanup the work directory after execution. + for attempt := 0; attempt < 5; attempt++ { + err := os.RemoveAll(s.WorkDirectory) + if err != nil { + // On Windows, open files cannot be removed. + // When the provisioner daemon is shutting down, + // it may take a few milliseconds for processes to exit. + // See: https://github.com/golang/go/issues/50510 + s.Logger.Debug(s.Context(), "failed to clean work directory; trying again", slog.Error(err)) + time.Sleep(250 * time.Millisecond) + continue + } + s.Logger.Debug(s.Context(), "cleaned up work directory") + break + } + }() + req, err := stream.Recv() + if err != nil { + return xerrors.Errorf("receive config: %w", err) + } + config := req.GetConfig() + if config == nil { + return xerrors.New("first request must be Config") + } + s.Config = config + if s.Config.ProvisionerLogLevel != "" { + s.logLevel = proto.LogLevel_value[strings.ToUpper(s.Config.ProvisionerLogLevel)] + } + + err = s.ExtractArchive() + if err != nil { + return xerrors.Errorf("extract archive: %w", err) + } + return s.handleRequests() +} + +func (s *Session) requestReader() <-chan *proto.Request { + ch := make(chan *proto.Request) + go func() { + defer close(ch) + for { + req, err := s.stream.Recv() + if err != nil { + s.Logger.Info(s.Context(), "recv done on Session", slog.Error(err)) + return + } + ch <- req + } + }() + return ch +} + +func (s *Session) handleRequests() error { + requests := s.requestReader() + planned := false + for req := range requests { + if req.GetCancel() != nil { + s.Logger.Warn(s.Context(), "ignoring cancel before request or after complete") + continue + } + resp := &proto.Response{} + if parse := req.GetParse(); parse != nil { + r := &request[*proto.ParseRequest, *proto.ParseComplete]{ + req: parse, + session: s, + serverFn: s.server.Parse, + cancels: requests, + } + complete, err := r.do() + if err != nil { + return err + } + // Handle README centrally, so that individual provisioners don't need to mess with it. + readme, err := os.ReadFile(filepath.Join(s.WorkDirectory, ReadmeFile)) + if err == nil { + complete.Readme = readme + } else { + s.Logger.Debug(s.Context(), "failed to parse readme (missing ok)", slog.Error(err)) + } + resp.Type = &proto.Response_Parse{Parse: complete} + } + if plan := req.GetPlan(); plan != nil { + r := &request[*proto.PlanRequest, *proto.PlanComplete]{ + req: plan, + session: s, + serverFn: s.server.Plan, + cancels: requests, + } + complete, err := r.do() + if err != nil { + return err + } + resp.Type = &proto.Response_Plan{Plan: complete} + if complete.Error == "" { + planned = true + } + } + if apply := req.GetApply(); apply != nil { + if !planned { + return xerrors.New("cannot apply before successful plan") + } + r := &request[*proto.ApplyRequest, *proto.ApplyComplete]{ + req: apply, + session: s, + serverFn: s.server.Apply, + cancels: requests, + } + complete, err := r.do() + if err != nil { + return err + } + resp.Type = &proto.Response_Apply{Apply: complete} + } + err := s.stream.Send(resp) + if err != nil { + return xerrors.Errorf("send response: %w", err) + } + } + return nil +} + +type Session struct { + Logger slog.Logger + WorkDirectory string + Config *proto.Config + + server Server + stream proto.DRPCProvisioner_SessionStream + logLevel int32 +} + +func (s *Session) Context() context.Context { + return s.stream.Context() +} + +func (s *Session) ExtractArchive() error { + ctx := s.Context() + + //s.ProvisionLog(proto.LogLevel_INFO, "Setting up") + + s.Logger.Info(ctx, "unpacking template source archive", + slog.F("size_bytes", len(s.Config.TemplateSourceArchive)), + ) + + reader := tar.NewReader(bytes.NewBuffer(s.Config.TemplateSourceArchive)) + // for safety, nil out the reference on Config, since the reader now owns it. + s.Config.TemplateSourceArchive = nil + for { + header, err := reader.Next() + if err != nil { + if xerrors.Is(err, io.EOF) { + break + } + return xerrors.Errorf("read template source archive: %w", err) + } + // #nosec + headerPath := filepath.Join(s.WorkDirectory, header.Name) + if !strings.HasPrefix(headerPath, filepath.Clean(s.WorkDirectory)) { + return xerrors.New("tar attempts to target relative upper directory") + } + mode := header.FileInfo().Mode() + if mode == 0 { + mode = 0o600 + } + switch header.Typeflag { + case tar.TypeDir: + err = os.MkdirAll(headerPath, mode) + if err != nil { + return xerrors.Errorf("mkdir %q: %w", headerPath, err) + } + s.Logger.Debug(context.Background(), "extracted directory", slog.F("path", headerPath)) + case tar.TypeReg: + file, err := os.OpenFile(headerPath, os.O_CREATE|os.O_RDWR, mode) + if err != nil { + return xerrors.Errorf("create file %q (mode %s): %w", headerPath, mode, err) + } + // Max file size of 10MiB. + size, err := io.CopyN(file, reader, 10<<20) + if xerrors.Is(err, io.EOF) { + err = nil + } + if err != nil { + _ = file.Close() + return xerrors.Errorf("copy file %q: %w", headerPath, err) + } + err = file.Close() + if err != nil { + return xerrors.Errorf("close file %q: %s", headerPath, err) + } + s.Logger.Debug(context.Background(), "extracted file", + slog.F("size_bytes", size), + slog.F("path", headerPath), + slog.F("mode", mode), + ) + } + } + return nil +} + +func (s *Session) ProvisionLog(level proto.LogLevel, output string) { + if int32(level) < s.logLevel { + return + } + + err := s.stream.Send(&proto.Response{Type: &proto.Response_Log{Log: &proto.Log{ + Level: level, + Output: output, + }}}) + if err != nil { + s.Logger.Error(s.Context(), "failed to transmit log", + slog.F("level", level), slog.F("output", output)) + } +} + +type pRequest interface { + *proto.ParseRequest | *proto.PlanRequest | *proto.ApplyRequest +} + +type pComplete interface { + *proto.ParseComplete | *proto.PlanComplete | *proto.ApplyComplete +} + +// request processes a single request call to the Server and returns its complete result, while also processing cancel +// requests from the daemon. Provisioner implementations read from canceledOrComplete to be asynchronously informed +// of cancel. +type request[R pRequest, C pComplete] struct { + req R + session *Session + cancels <-chan *proto.Request + serverFn func(*Session, R, <-chan struct{}) C +} + +func (r *request[R, C]) do() (C, error) { + canceledOrComplete := make(chan struct{}) + result := make(chan C) + go func() { + c := r.serverFn(r.session, r.req, canceledOrComplete) + result <- c + }() + select { + case req := <-r.cancels: + close(canceledOrComplete) + // wait for server to complete the request, even though we have canceled, + // so that we can't start a new request, and so that if the job was close + // to completion and the cancel was ignored, we return to complete. + c := <-result + // verify we got a cancel instead of another request or closed channel --- which is an error! + if req.GetCancel() != nil { + return c, nil + } + return c, xerrors.Errorf("got new request or nil while old request still processing", + slog.F("request", req)) + case c := <-result: + close(canceledOrComplete) + return c, nil + } +} diff --git a/provisionersdk/transport.go b/provisionersdk/transport.go index 19730d3bf0530..f5df895d64eaa 100644 --- a/provisionersdk/transport.go +++ b/provisionersdk/transport.go @@ -19,7 +19,7 @@ const ( MaxMessageSize = 4 << 20 ) -// MultiplexedConn returns a multiplexed dRPC connection from a yamux session. +// MultiplexedConn returns a multiplexed dRPC connection from a yamux Session. func MultiplexedConn(session *yamux.Session) drpc.Conn { return &multiplexedDRPC{session} } From 1f0efb47883637dde60d71fc69360e1fca54f6ac Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Wed, 23 Aug 2023 08:23:40 +0000 Subject: [PATCH 03/13] refactor provisionerd to use new protocol Signed-off-by: Spike Curtis --- cli/server.go | 12 +- coderd/coderdtest/coderdtest.go | 17 +- enterprise/cli/provisionerdaemons.go | 16 +- provisionerd/provisionerd.go | 9 - provisionerd/provisionerd_test.go | 452 ++++++++++++++------------- provisionerd/runner/runner.go | 407 ++++++++++-------------- 6 files changed, 415 insertions(+), 498 deletions(-) diff --git a/cli/server.go b/cli/server.go index 1cd6ec475747a..0ac71095065ee 100644 --- a/cli/server.go +++ b/cli/server.go @@ -41,7 +41,6 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/spf13/afero" "go.opentelemetry.io/otel/trace" "golang.org/x/mod/semver" "golang.org/x/oauth2" @@ -1304,7 +1303,10 @@ func newProvisionerDaemon( defer wg.Done() defer cancel() - err := echo.Serve(ctx, afero.NewOsFs(), &provisionersdk.ServeOptions{Listener: echoServer}) + err := echo.Serve(ctx, &provisionersdk.ServeOptions{ + Listener: echoServer, + WorkDirectory: workDir, + }) if err != nil { select { case errCh <- err: @@ -1336,10 +1338,11 @@ func newProvisionerDaemon( err := terraform.Serve(ctx, &terraform.ServeOptions{ ServeOptions: &provisionersdk.ServeOptions{ - Listener: terraformServer, + Listener: terraformServer, + Logger: logger.Named("terraform"), + WorkDirectory: workDir, }, CachePath: tfDir, - Logger: logger.Named("terraform"), Tracer: tracer, }) if err != nil && !xerrors.Is(err, context.Canceled) { @@ -1366,7 +1369,6 @@ func newProvisionerDaemon( UpdateInterval: time.Second, ForceCancelInterval: cfg.Provisioner.ForceCancelInterval.Value(), Provisioners: provisioners, - WorkDirectory: workDir, TracerProvider: coderAPI.TracerProvider, Metrics: &metrics, }), nil diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go index bc2cb5e5925a0..4ea2b82413567 100644 --- a/coderd/coderdtest/coderdtest.go +++ b/coderd/coderdtest/coderdtest.go @@ -37,7 +37,6 @@ import ( "github.com/google/uuid" "github.com/moby/moby/pkg/namesgenerator" "github.com/prometheus/client_golang/prometheus" - "github.com/spf13/afero" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/oauth2" @@ -469,10 +468,10 @@ func NewProvisionerDaemon(t testing.TB, coderAPI *coderd.API) io.Closer { _ = echoServer.Close() cancelFunc() }) - fs := afero.NewMemMapFs() go func() { - err := echo.Serve(ctx, fs, &provisionersdk.ServeOptions{ - Listener: echoServer, + err := echo.Serve(ctx, &provisionersdk.ServeOptions{ + Listener: echoServer, + WorkDirectory: t.TempDir(), }) assert.NoError(t, err) }() @@ -480,7 +479,6 @@ func NewProvisionerDaemon(t testing.TB, coderAPI *coderd.API) io.Closer { closer := provisionerd.New(func(ctx context.Context) (provisionerdproto.DRPCProvisionerDaemonClient, error) { return coderAPI.CreateInMemoryProvisionerDaemon(ctx, 0) }, &provisionerd.Options{ - Filesystem: fs, Logger: coderAPI.Logger.Named("provisionerd").Leveled(slog.LevelDebug), JobPollInterval: 50 * time.Millisecond, UpdateInterval: 250 * time.Millisecond, @@ -488,7 +486,6 @@ func NewProvisionerDaemon(t testing.TB, coderAPI *coderd.API) io.Closer { Provisioners: provisionerd.Provisioners{ string(database.ProvisionerTypeEcho): sdkproto.NewDRPCProvisionerClient(echoClient), }, - WorkDirectory: t.TempDir(), }) t.Cleanup(func() { _ = closer.Close() @@ -506,11 +503,11 @@ func NewExternalProvisionerDaemon(t *testing.T, client *codersdk.Client, org uui cancelFunc() <-serveDone }) - fs := afero.NewMemMapFs() go func() { defer close(serveDone) - err := echo.Serve(ctx, fs, &provisionersdk.ServeOptions{ - Listener: echoServer, + err := echo.Serve(ctx, &provisionersdk.ServeOptions{ + Listener: echoServer, + WorkDirectory: t.TempDir(), }) assert.NoError(t, err) }() @@ -522,7 +519,6 @@ func NewExternalProvisionerDaemon(t *testing.T, client *codersdk.Client, org uui Tags: tags, }) }, &provisionerd.Options{ - Filesystem: fs, Logger: slogtest.Make(t, nil).Named("provisionerd").Leveled(slog.LevelDebug), JobPollInterval: 50 * time.Millisecond, UpdateInterval: 250 * time.Millisecond, @@ -530,7 +526,6 @@ func NewExternalProvisionerDaemon(t *testing.T, client *codersdk.Client, org uui Provisioners: provisionerd.Provisioners{ string(database.ProvisionerTypeEcho): sdkproto.NewDRPCProvisionerClient(echoClient), }, - WorkDirectory: t.TempDir(), }) t.Cleanup(func() { _ = closer.Close() diff --git a/enterprise/cli/provisionerdaemons.go b/enterprise/cli/provisionerdaemons.go index 82d853503ace4..e46756578d542 100644 --- a/enterprise/cli/provisionerdaemons.go +++ b/enterprise/cli/provisionerdaemons.go @@ -70,6 +70,11 @@ func (r *RootCmd) provisionerDaemonStart() *clibase.Cmd { return xerrors.Errorf("mkdir %q: %w", cacheDir, err) } + tempDir, err := os.MkdirTemp("", "provisionerd") + if err != nil { + return err + } + terraformClient, terraformServer := provisionersdk.MemTransportPipe() go func() { <-ctx.Done() @@ -84,10 +89,11 @@ func (r *RootCmd) provisionerDaemonStart() *clibase.Cmd { err := terraform.Serve(ctx, &terraform.ServeOptions{ ServeOptions: &provisionersdk.ServeOptions{ - Listener: terraformServer, + Listener: terraformServer, + Logger: logger.Named("terraform"), + WorkDirectory: tempDir, }, CachePath: cacheDir, - Logger: logger.Named("terraform"), }) if err != nil && !xerrors.Is(err, context.Canceled) { select { @@ -97,11 +103,6 @@ func (r *RootCmd) provisionerDaemonStart() *clibase.Cmd { } }() - tempDir, err := os.MkdirTemp("", "provisionerd") - if err != nil { - return err - } - logger.Info(ctx, "starting provisioner daemon", slog.F("tags", tags)) provisioners := provisionerd.Provisioners{ @@ -121,7 +122,6 @@ func (r *RootCmd) provisionerDaemonStart() *clibase.Cmd { JobPollJitter: pollJitter, UpdateInterval: 500 * time.Millisecond, Provisioners: provisioners, - WorkDirectory: tempDir, }) var exitErr error diff --git a/provisionerd/provisionerd.go b/provisionerd/provisionerd.go index f127ab7b584bd..a341bd5a3df85 100644 --- a/provisionerd/provisionerd.go +++ b/provisionerd/provisionerd.go @@ -12,7 +12,6 @@ import ( "github.com/hashicorp/yamux" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/spf13/afero" "github.com/valyala/fasthttp/fasthttputil" "go.opentelemetry.io/otel/attribute" semconv "go.opentelemetry.io/otel/semconv/v1.14.0" @@ -44,7 +43,6 @@ type Provisioners map[string]sdkproto.DRPCProvisionerClient // Options provides customizations to the behavior of a provisioner daemon. type Options struct { - Filesystem afero.Fs Logger slog.Logger TracerProvider trace.TracerProvider Metrics *Metrics @@ -56,8 +54,6 @@ type Options struct { JobPollJitter time.Duration JobPollDebounce time.Duration Provisioners Provisioners - // WorkDirectory must not be used by multiple processes at once. - WorkDirectory string } // New creates and starts a provisioner daemon. @@ -80,9 +76,6 @@ func New(clientDialer Dialer, opts *Options) *Server { if opts.LogBufferInterval == 0 { opts.LogBufferInterval = 250 * time.Millisecond } - if opts.Filesystem == nil { - opts.Filesystem = afero.NewOsFs() - } if opts.TracerProvider == nil { opts.TracerProvider = trace.NewNoopTracerProvider() } @@ -405,8 +398,6 @@ func (p *Server) acquireJob(ctx context.Context) { Updater: p, QuotaCommitter: p, Logger: p.opts.Logger.Named("runner"), - Filesystem: p.opts.Filesystem, - WorkDirectory: p.opts.WorkDirectory, Provisioner: provisioner, UpdateInterval: p.opts.UpdateInterval, ForceCancelInterval: p.opts.ForceCancelInterval, diff --git a/provisionerd/provisionerd_test.go b/provisionerd/provisionerd_test.go index 90b9923996be9..ee379e0ab9929 100644 --- a/provisionerd/provisionerd_test.go +++ b/provisionerd/provisionerd_test.go @@ -25,7 +25,6 @@ import ( "cdr.dev/slog/sloggers/slogtest" "github.com/coder/coder/v2/provisionerd" "github.com/coder/coder/v2/provisionerd/proto" - "github.com/coder/coder/v2/provisionerd/runner" "github.com/coder/coder/v2/provisionersdk" sdkproto "github.com/coder/coder/v2/provisionersdk/proto" "github.com/coder/coder/v2/testutil" @@ -129,7 +128,7 @@ func TestProvisionerd(t *testing.T) { }), Type: &proto.AcquiredJob_TemplateImport_{ TemplateImport: &proto.AcquiredJob_TemplateImport{ - Metadata: &sdkproto.Provision_Metadata{}, + Metadata: &sdkproto.Metadata{}, }, }, }, nil @@ -144,10 +143,15 @@ func TestProvisionerd(t *testing.T) { }), nil }, provisionerd.Provisioners{ "someprovisioner": createProvisionerClient(t, done, provisionerTestServer{ - parse: func(request *sdkproto.Parse_Request, stream sdkproto.DRPCProvisioner_ParseStream) error { + parse: func(_ *provisionersdk.Session, _ *sdkproto.ParseRequest, _ <-chan struct{}) *sdkproto.ParseComplete { closerMutex.Lock() defer closerMutex.Unlock() - return closer.Close() + err := closer.Close() + c := &sdkproto.ParseComplete{} + if err != nil { + c.Error = err.Error() + } + return c }, }), }) @@ -180,7 +184,7 @@ func TestProvisionerd(t *testing.T) { }), Type: &proto.AcquiredJob_TemplateImport_{ TemplateImport: &proto.AcquiredJob_TemplateImport{ - Metadata: &sdkproto.Provision_Metadata{}, + Metadata: &sdkproto.Metadata{}, }, }, }, nil @@ -220,7 +224,7 @@ func TestProvisionerd(t *testing.T) { }), Type: &proto.AcquiredJob_TemplateImport_{ TemplateImport: &proto.AcquiredJob_TemplateImport{ - Metadata: &sdkproto.Provision_Metadata{}, + Metadata: &sdkproto.Metadata{}, }, }, }, nil @@ -235,9 +239,13 @@ func TestProvisionerd(t *testing.T) { }), nil }, provisionerd.Provisioners{ "someprovisioner": createProvisionerClient(t, done, provisionerTestServer{ - parse: func(request *sdkproto.Parse_Request, stream sdkproto.DRPCProvisioner_ParseStream) error { - <-stream.Context().Done() - return nil + parse: func( + _ *provisionersdk.Session, + _ *sdkproto.ParseRequest, + cancelOrComplete <-chan struct{}, + ) *sdkproto.ParseComplete { + <-cancelOrComplete + return &sdkproto.ParseComplete{} }, }), }) @@ -255,7 +263,6 @@ func TestProvisionerd(t *testing.T) { didComplete atomic.Bool didLog atomic.Bool didAcquireJob atomic.Bool - didDryRun = atomic.NewBool(true) didReadme atomic.Bool completeChan = make(chan struct{}) completeOnce sync.Once @@ -273,12 +280,12 @@ func TestProvisionerd(t *testing.T) { JobId: "test", Provisioner: "someprovisioner", TemplateSourceArchive: createTar(t, map[string]string{ - "test.txt": "content", - runner.ReadmeFile: "# A cool template 😎\n", + "test.txt": "content", + provisionersdk.ReadmeFile: "# A cool template 😎\n", }), Type: &proto.AcquiredJob_TemplateImport_{ TemplateImport: &proto.AcquiredJob_TemplateImport{ - Metadata: &sdkproto.Provision_Metadata{}, + Metadata: &sdkproto.Metadata{}, }, }, }, nil @@ -299,54 +306,34 @@ func TestProvisionerd(t *testing.T) { }), nil }, provisionerd.Provisioners{ "someprovisioner": createProvisionerClient(t, done, provisionerTestServer{ - parse: func(request *sdkproto.Parse_Request, stream sdkproto.DRPCProvisioner_ParseStream) error { - data, err := os.ReadFile(filepath.Join(request.Directory, "test.txt")) + parse: func( + s *provisionersdk.Session, + _ *sdkproto.ParseRequest, + cancelOrComplete <-chan struct{}, + ) *sdkproto.ParseComplete { + data, err := os.ReadFile(filepath.Join(s.WorkDirectory, "test.txt")) require.NoError(t, err) require.Equal(t, "content", string(data)) - - err = stream.Send(&sdkproto.Parse_Response{ - Type: &sdkproto.Parse_Response_Log{ - Log: &sdkproto.Log{ - Level: sdkproto.LogLevel_INFO, - Output: "hello", - }, - }, - }) - require.NoError(t, err) - - err = stream.Send(&sdkproto.Parse_Response{ - Type: &sdkproto.Parse_Response_Complete{ - Complete: &sdkproto.Parse_Complete{}, - }, - }) - require.NoError(t, err) - return nil + s.ProvisionLog(sdkproto.LogLevel_INFO, "hello") + return &sdkproto.ParseComplete{} }, - provision: func(stream sdkproto.DRPCProvisioner_ProvisionStream) error { - request, err := stream.Recv() - require.NoError(t, err) - if request.GetApply() != nil { - didDryRun.Store(false) + plan: func( + s *provisionersdk.Session, + _ *sdkproto.PlanRequest, + cancelOrComplete <-chan struct{}, + ) *sdkproto.PlanComplete { + s.ProvisionLog(sdkproto.LogLevel_INFO, "hello") + return &sdkproto.PlanComplete{ + Resources: []*sdkproto.Resource{}, } - err = stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Log{ - Log: &sdkproto.Log{ - Level: sdkproto.LogLevel_INFO, - Output: "hello", - }, - }, - }) - require.NoError(t, err) - - err = stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Complete{ - Complete: &sdkproto.Provision_Complete{ - Resources: []*sdkproto.Resource{}, - }, - }, - }) - require.NoError(t, err) - return nil + }, + apply: func( + _ *provisionersdk.Session, + _ *sdkproto.ApplyRequest, + _ <-chan struct{}, + ) *sdkproto.ApplyComplete { + t.Error("dry run should not apply") + return &sdkproto.ApplyComplete{} }, }), }) @@ -355,7 +342,6 @@ func TestProvisionerd(t *testing.T) { require.NoError(t, closer.Close()) assert.True(t, didLog.Load(), "should log some updates") assert.True(t, didComplete.Load(), "should complete the job") - assert.True(t, didDryRun.Load(), "should be a dry run") }) t.Run("TemplateDryRun", func(t *testing.T) { @@ -371,7 +357,7 @@ func TestProvisionerd(t *testing.T) { completeChan = make(chan struct{}) completeOnce sync.Once - metadata = &sdkproto.Provision_Metadata{} + metadata = &sdkproto.Metadata{} ) closer := createProvisionerd(t, func(ctx context.Context) (proto.DRPCProvisionerDaemonClient, error) { @@ -414,16 +400,22 @@ func TestProvisionerd(t *testing.T) { }), nil }, provisionerd.Provisioners{ "someprovisioner": createProvisionerClient(t, done, provisionerTestServer{ - provision: func(stream sdkproto.DRPCProvisioner_ProvisionStream) error { - err := stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Complete{ - Complete: &sdkproto.Provision_Complete{ - Resources: []*sdkproto.Resource{}, - }, - }, - }) - require.NoError(t, err) - return nil + plan: func( + _ *provisionersdk.Session, + _ *sdkproto.PlanRequest, + _ <-chan struct{}, + ) *sdkproto.PlanComplete { + return &sdkproto.PlanComplete{ + Resources: []*sdkproto.Resource{}, + } + }, + apply: func( + _ *provisionersdk.Session, + _ *sdkproto.ApplyRequest, + _ <-chan struct{}, + ) *sdkproto.ApplyComplete { + t.Error("dry run should not apply") + return &sdkproto.ApplyComplete{} }, }), }) @@ -464,7 +456,7 @@ func TestProvisionerd(t *testing.T) { }), Type: &proto.AcquiredJob_WorkspaceBuild_{ WorkspaceBuild: &proto.AcquiredJob_WorkspaceBuild{ - Metadata: &sdkproto.Provision_Metadata{}, + Metadata: &sdkproto.Metadata{}, }, }, }, nil @@ -482,24 +474,20 @@ func TestProvisionerd(t *testing.T) { }), nil }, provisionerd.Provisioners{ "someprovisioner": createProvisionerClient(t, done, provisionerTestServer{ - provision: func(stream sdkproto.DRPCProvisioner_ProvisionStream) error { - err := stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Log{ - Log: &sdkproto.Log{ - Level: sdkproto.LogLevel_DEBUG, - Output: "wow", - }, - }, - }) - require.NoError(t, err) - - err = stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Complete{ - Complete: &sdkproto.Provision_Complete{}, - }, - }) - require.NoError(t, err) - return nil + plan: func( + s *provisionersdk.Session, + _ *sdkproto.PlanRequest, + cancelOrComplete <-chan struct{}, + ) *sdkproto.PlanComplete { + s.ProvisionLog(sdkproto.LogLevel_DEBUG, "wow") + return &sdkproto.PlanComplete{} + }, + apply: func( + _ *provisionersdk.Session, + _ *sdkproto.ApplyRequest, + _ <-chan struct{}, + ) *sdkproto.ApplyComplete { + return &sdkproto.ApplyComplete{} }, }), }) @@ -540,7 +528,7 @@ func TestProvisionerd(t *testing.T) { }), Type: &proto.AcquiredJob_WorkspaceBuild_{ WorkspaceBuild: &proto.AcquiredJob_WorkspaceBuild{ - Metadata: &sdkproto.Provision_Metadata{}, + Metadata: &sdkproto.Metadata{}, }, }, }, nil @@ -567,40 +555,46 @@ func TestProvisionerd(t *testing.T) { }), nil }, provisionerd.Provisioners{ "someprovisioner": createProvisionerClient(t, done, provisionerTestServer{ - provision: func(stream sdkproto.DRPCProvisioner_ProvisionStream) error { - err := stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Log{ - Log: &sdkproto.Log{ - Level: sdkproto.LogLevel_DEBUG, - Output: "wow", + plan: func( + s *provisionersdk.Session, + _ *sdkproto.PlanRequest, + cancelOrComplete <-chan struct{}, + ) *sdkproto.PlanComplete { + s.ProvisionLog(sdkproto.LogLevel_DEBUG, "wow") + return &sdkproto.PlanComplete{ + Resources: []*sdkproto.Resource{ + { + DailyCost: 10, + }, + { + DailyCost: 15, }, }, - }) - require.NoError(t, err) - - err = stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Complete{ - Complete: &sdkproto.Provision_Complete{ - Resources: []*sdkproto.Resource{ - { - DailyCost: 10, - }, - { - DailyCost: 15, - }, - }, + } + }, + apply: func( + _ *provisionersdk.Session, + _ *sdkproto.ApplyRequest, + _ <-chan struct{}, + ) *sdkproto.ApplyComplete { + t.Error("should not apply when resources exceed quota") + return &sdkproto.ApplyComplete{ + Resources: []*sdkproto.Resource{ + { + DailyCost: 10, + }, + { + DailyCost: 15, }, }, - }) - require.NoError(t, err) - return nil + } }, }), }) require.Condition(t, closedWithin(completeChan, testutil.WaitShort)) require.NoError(t, closer.Close()) assert.True(t, didLog.Load(), "should log some updates") - assert.False(t, didComplete.Load(), "should complete the job") + assert.False(t, didComplete.Load(), "should not complete the job") assert.True(t, didFail.Load(), "should fail the job") }) @@ -633,7 +627,7 @@ func TestProvisionerd(t *testing.T) { }), Type: &proto.AcquiredJob_WorkspaceBuild_{ WorkspaceBuild: &proto.AcquiredJob_WorkspaceBuild{ - Metadata: &sdkproto.Provision_Metadata{}, + Metadata: &sdkproto.Metadata{}, }, }, }, nil @@ -646,14 +640,24 @@ func TestProvisionerd(t *testing.T) { }), nil }, provisionerd.Provisioners{ "someprovisioner": createProvisionerClient(t, done, provisionerTestServer{ - provision: func(stream sdkproto.DRPCProvisioner_ProvisionStream) error { - return stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Complete{ - Complete: &sdkproto.Provision_Complete{ - Error: "some error", - }, - }, - }) + plan: func( + s *provisionersdk.Session, + _ *sdkproto.PlanRequest, + cancelOrComplete <-chan struct{}, + ) *sdkproto.PlanComplete { + return &sdkproto.PlanComplete{ + Error: "some error", + } + }, + apply: func( + _ *provisionersdk.Session, + _ *sdkproto.ApplyRequest, + _ <-chan struct{}, + ) *sdkproto.ApplyComplete { + t.Error("should not apply when plan errors") + return &sdkproto.ApplyComplete{ + Error: "some error", + } }, }), }) @@ -683,7 +687,7 @@ func TestProvisionerd(t *testing.T) { }), Type: &proto.AcquiredJob_WorkspaceBuild_{ WorkspaceBuild: &proto.AcquiredJob_WorkspaceBuild{ - Metadata: &sdkproto.Provision_Metadata{}, + Metadata: &sdkproto.Metadata{}, }, }, }, nil @@ -712,31 +716,24 @@ func TestProvisionerd(t *testing.T) { }), nil }, provisionerd.Provisioners{ "someprovisioner": createProvisionerClient(t, done, provisionerTestServer{ - provision: func(stream sdkproto.DRPCProvisioner_ProvisionStream) error { - // Ignore the first provision message! - _, _ = stream.Recv() - - err := stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Log{ - Log: &sdkproto.Log{ - Level: sdkproto.LogLevel_DEBUG, - Output: "in progress", - }, - }, - }) - require.NoError(t, err) - - msg, err := stream.Recv() - require.NoError(t, err) - require.NotNil(t, msg.GetCancel()) - - return stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Complete{ - Complete: &sdkproto.Provision_Complete{ - Error: "some error", - }, - }, - }) + plan: func( + s *provisionersdk.Session, + _ *sdkproto.PlanRequest, + canceledOrComplete <-chan struct{}, + ) *sdkproto.PlanComplete { + s.ProvisionLog(sdkproto.LogLevel_DEBUG, "in progress") + <-canceledOrComplete + return &sdkproto.PlanComplete{ + Error: "some error", + } + }, + apply: func( + _ *provisionersdk.Session, + _ *sdkproto.ApplyRequest, + _ <-chan struct{}, + ) *sdkproto.ApplyComplete { + t.Error("should not apply when shut down during plan") + return &sdkproto.ApplyComplete{} }, }), }) @@ -768,7 +765,7 @@ func TestProvisionerd(t *testing.T) { }), Type: &proto.AcquiredJob_WorkspaceBuild_{ WorkspaceBuild: &proto.AcquiredJob_WorkspaceBuild{ - Metadata: &sdkproto.Provision_Metadata{}, + Metadata: &sdkproto.Metadata{}, }, }, }, nil @@ -805,31 +802,24 @@ func TestProvisionerd(t *testing.T) { }), nil }, provisionerd.Provisioners{ "someprovisioner": createProvisionerClient(t, done, provisionerTestServer{ - provision: func(stream sdkproto.DRPCProvisioner_ProvisionStream) error { - // Ignore the first provision message! - _, _ = stream.Recv() - - err := stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Log{ - Log: &sdkproto.Log{ - Level: sdkproto.LogLevel_DEBUG, - Output: "in progress", - }, - }, - }) - require.NoError(t, err) - - msg, err := stream.Recv() - require.NoError(t, err) - require.NotNil(t, msg.GetCancel()) - - return stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Complete{ - Complete: &sdkproto.Provision_Complete{ - Error: "some error", - }, - }, - }) + plan: func( + s *provisionersdk.Session, + _ *sdkproto.PlanRequest, + canceledOrComplete <-chan struct{}, + ) *sdkproto.PlanComplete { + s.ProvisionLog(sdkproto.LogLevel_DEBUG, "in progress") + <-canceledOrComplete + return &sdkproto.PlanComplete{ + Error: "some error", + } + }, + apply: func( + _ *provisionersdk.Session, + _ *sdkproto.ApplyRequest, + _ <-chan struct{}, + ) *sdkproto.ApplyComplete { + t.Error("should not apply when shut down during plan") + return &sdkproto.ApplyComplete{} }, }), }) @@ -867,7 +857,7 @@ func TestProvisionerd(t *testing.T) { }), Type: &proto.AcquiredJob_WorkspaceBuild_{ WorkspaceBuild: &proto.AcquiredJob_WorkspaceBuild{ - Metadata: &sdkproto.Provision_Metadata{}, + Metadata: &sdkproto.Metadata{}, }, }, }, nil @@ -898,16 +888,22 @@ func TestProvisionerd(t *testing.T) { return client, nil }, provisionerd.Provisioners{ "someprovisioner": createProvisionerClient(t, done, provisionerTestServer{ - provision: func(stream sdkproto.DRPCProvisioner_ProvisionStream) error { - // Ignore the first provision message! - _, _ = stream.Recv() - return stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Complete{ - Complete: &sdkproto.Provision_Complete{ - Error: "some error", - }, - }, - }) + plan: func( + _ *provisionersdk.Session, + _ *sdkproto.PlanRequest, + _ <-chan struct{}, + ) *sdkproto.PlanComplete { + return &sdkproto.PlanComplete{ + Error: "some error", + } + }, + apply: func( + _ *provisionersdk.Session, + _ *sdkproto.ApplyRequest, + _ <-chan struct{}, + ) *sdkproto.ApplyComplete { + t.Error("should not apply when error during plan") + return &sdkproto.ApplyComplete{} }, }), }) @@ -945,7 +941,7 @@ func TestProvisionerd(t *testing.T) { }), Type: &proto.AcquiredJob_WorkspaceBuild_{ WorkspaceBuild: &proto.AcquiredJob_WorkspaceBuild{ - Metadata: &sdkproto.Provision_Metadata{}, + Metadata: &sdkproto.Metadata{}, }, }, }, nil @@ -977,14 +973,19 @@ func TestProvisionerd(t *testing.T) { return client, nil }, provisionerd.Provisioners{ "someprovisioner": createProvisionerClient(t, done, provisionerTestServer{ - provision: func(stream sdkproto.DRPCProvisioner_ProvisionStream) error { - // Ignore the first provision message! - _, _ = stream.Recv() - return stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Complete{ - Complete: &sdkproto.Provision_Complete{}, - }, - }) + plan: func( + _ *provisionersdk.Session, + _ *sdkproto.PlanRequest, + _ <-chan struct{}, + ) *sdkproto.PlanComplete { + return &sdkproto.PlanComplete{} + }, + apply: func( + _ *provisionersdk.Session, + _ *sdkproto.ApplyRequest, + _ <-chan struct{}, + ) *sdkproto.ApplyComplete { + return &sdkproto.ApplyComplete{} }, }), }) @@ -1023,7 +1024,7 @@ func TestProvisionerd(t *testing.T) { }), Type: &proto.AcquiredJob_WorkspaceBuild_{ WorkspaceBuild: &proto.AcquiredJob_WorkspaceBuild{ - Metadata: &sdkproto.Provision_Metadata{}, + Metadata: &sdkproto.Metadata{}, }, }, }, nil @@ -1056,24 +1057,21 @@ func TestProvisionerd(t *testing.T) { }), nil }, provisionerd.Provisioners{ "someprovisioner": createProvisionerClient(t, done, provisionerTestServer{ - provision: func(stream sdkproto.DRPCProvisioner_ProvisionStream) error { - err := stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Log{ - Log: &sdkproto.Log{ - Level: sdkproto.LogLevel_DEBUG, - Output: "wow", - }, - }, - }) - require.NoError(t, err) - - err = stream.Send(&sdkproto.Provision_Response{ - Type: &sdkproto.Provision_Response_Complete{ - Complete: &sdkproto.Provision_Complete{}, - }, - }) - require.NoError(t, err) - return nil + plan: func( + s *provisionersdk.Session, + _ *sdkproto.PlanRequest, + _ <-chan struct{}, + ) *sdkproto.PlanComplete { + s.ProvisionLog(sdkproto.LogLevel_DEBUG, "wow") + return &sdkproto.PlanComplete{} + }, + apply: func( + s *provisionersdk.Session, + _ *sdkproto.ApplyRequest, + _ <-chan struct{}, + ) *sdkproto.ApplyComplete { + s.ProvisionLog(sdkproto.LogLevel_DEBUG, "wow") + return &sdkproto.ApplyComplete{} }, }), }) @@ -1111,7 +1109,6 @@ func createProvisionerd(t *testing.T, dialer provisionerd.Dialer, provisioners p JobPollInterval: 50 * time.Millisecond, UpdateInterval: 50 * time.Millisecond, Provisioners: provisioners, - WorkDirectory: t.TempDir(), }) t.Cleanup(func() { _ = server.Close() @@ -1172,15 +1169,15 @@ func createProvisionerClient(t *testing.T, done <-chan struct{}, server provisio _ = clientPipe.Close() _ = serverPipe.Close() }) - mux := drpcmux.New() - err := sdkproto.DRPCRegisterProvisioner(mux, &server) - require.NoError(t, err) - srv := drpcserver.New(mux) ctx, cancelFunc := context.WithCancel(context.Background()) closed := make(chan struct{}) go func() { defer close(closed) - _ = srv.Serve(ctx, serverPipe) + _ = provisionersdk.Serve(ctx, &server, &provisionersdk.ServeOptions{ + Listener: serverPipe, + Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug).Named("test-provisioner"), + WorkDirectory: t.TempDir(), + }) }() t.Cleanup(func() { cancelFunc() @@ -1200,16 +1197,21 @@ func createProvisionerClient(t *testing.T, done <-chan struct{}, server provisio } type provisionerTestServer struct { - parse func(request *sdkproto.Parse_Request, stream sdkproto.DRPCProvisioner_ParseStream) error - provision func(stream sdkproto.DRPCProvisioner_ProvisionStream) error + parse func(s *provisionersdk.Session, r *sdkproto.ParseRequest, canceledOrComplete <-chan struct{}) *sdkproto.ParseComplete + plan func(s *provisionersdk.Session, r *sdkproto.PlanRequest, canceledOrComplete <-chan struct{}) *sdkproto.PlanComplete + apply func(s *provisionersdk.Session, r *sdkproto.ApplyRequest, canceledOrComplete <-chan struct{}) *sdkproto.ApplyComplete +} + +func (p *provisionerTestServer) Parse(s *provisionersdk.Session, r *sdkproto.ParseRequest, canceledOrComplete <-chan struct{}) *sdkproto.ParseComplete { + return p.parse(s, r, canceledOrComplete) } -func (p *provisionerTestServer) Parse(request *sdkproto.Parse_Request, stream sdkproto.DRPCProvisioner_ParseStream) error { - return p.parse(request, stream) +func (p *provisionerTestServer) Plan(s *provisionersdk.Session, r *sdkproto.PlanRequest, canceledOrComplete <-chan struct{}) *sdkproto.PlanComplete { + return p.plan(s, r, canceledOrComplete) } -func (p *provisionerTestServer) Provision(stream sdkproto.DRPCProvisioner_ProvisionStream) error { - return p.provision(stream) +func (p *provisionerTestServer) Apply(s *provisionersdk.Session, r *sdkproto.ApplyRequest, canceledOrComplete <-chan struct{}) *sdkproto.ApplyComplete { + return p.apply(s, r, canceledOrComplete) } // Fulfills the protobuf interface for a ProvisionerDaemon with diff --git a/provisionerd/runner/runner.go b/provisionerd/runner/runner.go index 5911004f98e2e..d1843b43fb0ba 100644 --- a/provisionerd/runner/runner.go +++ b/provisionerd/runner/runner.go @@ -1,15 +1,9 @@ package runner import ( - "archive/tar" - "bytes" "context" "errors" "fmt" - "io" - "os" - "path" - "path/filepath" "reflect" "strings" "sync" @@ -18,7 +12,6 @@ import ( "github.com/google/uuid" "github.com/prometheus/client_golang/prometheus" - "github.com/spf13/afero" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" semconv "go.opentelemetry.io/otel/semconv/v1.14.0" @@ -54,14 +47,14 @@ type Runner struct { sender JobUpdater quotaCommitter QuotaCommitter logger slog.Logger - filesystem afero.Fs - workDirectory string provisioner sdkproto.DRPCProvisionerClient lastUpdate atomic.Pointer[time.Time] updateInterval time.Duration forceCancelInterval time.Duration logBufferInterval time.Duration + // session is the provisioning session with the (possibly remote) provisioner + session sdkproto.DRPCProvisioner_SessionClient // closed when the Runner is finished sending any updates/failed/complete. done chan struct{} // active as long as we are not canceled @@ -108,8 +101,6 @@ type Options struct { Updater JobUpdater QuotaCommitter QuotaCommitter Logger slog.Logger - Filesystem afero.Fs - WorkDirectory string Provisioner sdkproto.DRPCProvisionerClient UpdateInterval time.Duration ForceCancelInterval time.Duration @@ -149,8 +140,6 @@ func New( sender: opts.Updater, quotaCommitter: opts.QuotaCommitter, logger: logger, - filesystem: opts.Filesystem, - workDirectory: opts.WorkDirectory, provisioner: opts.Provisioner, updateInterval: opts.UpdateInterval, forceCancelInterval: opts.ForceCancelInterval, @@ -386,6 +375,14 @@ func (r *Runner) doCleanFinish(ctx context.Context) { r.setComplete(completedJob) }() + var err error + r.session, err = r.provisioner.Session(ctx) + if err != nil { + failedJob = r.failedJobf("open session: %s", err) + return + } + defer r.session.Close() + defer func() { ctx, span := r.startTrace(ctx, tracing.FuncName()) defer span.End() @@ -396,23 +393,6 @@ func (r *Runner) doCleanFinish(ctx context.Context) { Stage: "Cleaning Up", CreatedAt: time.Now().UnixMilli(), }) - - // Cleanup the work directory after execution. - for attempt := 0; attempt < 5; attempt++ { - err := r.filesystem.RemoveAll(r.workDirectory) - if err != nil { - // On Windows, open files cannot be removed. - // When the provisioner daemon is shutting down, - // it may take a few milliseconds for processes to exit. - // See: https://github.com/golang/go/issues/50510 - r.logger.Debug(ctx, "failed to clean work directory; trying again", slog.Error(err)) - time.Sleep(250 * time.Millisecond) - continue - } - r.logger.Debug(ctx, "cleaned up work directory") - break - } - r.flushQueuedLogs(ctx) }() @@ -424,85 +404,19 @@ func (r *Runner) do(ctx context.Context) (*proto.CompletedJob, *proto.FailedJob) ctx, span := r.startTrace(ctx, tracing.FuncName()) defer span.End() - err := r.filesystem.MkdirAll(r.workDirectory, 0o700) - if err != nil { - return nil, r.failedJobf("create work directory %q: %s", r.workDirectory, err) - } - r.queueLog(ctx, &proto.Log{ Source: proto.LogSource_PROVISIONER_DAEMON, Level: sdkproto.LogLevel_INFO, Stage: "Setting up", CreatedAt: time.Now().UnixMilli(), }) - if err != nil { - return nil, r.failedJobf("write log: %s", err) - } - - r.logger.Info(ctx, "unpacking template source archive", - slog.F("size_bytes", len(r.job.TemplateSourceArchive)), - ) - reader := tar.NewReader(bytes.NewBuffer(r.job.TemplateSourceArchive)) - for { - header, err := reader.Next() - if err != nil { - if errors.Is(err, io.EOF) { - break - } - return nil, r.failedJobf("read template source archive: %s", err) - } - // #nosec - headerPath := filepath.Join(r.workDirectory, header.Name) - if !strings.HasPrefix(headerPath, filepath.Clean(r.workDirectory)) { - return nil, r.failedJobf("tar attempts to target relative upper directory") - } - mode := header.FileInfo().Mode() - if mode == 0 { - mode = 0o600 - } - switch header.Typeflag { - case tar.TypeDir: - err = r.filesystem.MkdirAll(headerPath, mode) - if err != nil { - return nil, r.failedJobf("mkdir %q: %s", headerPath, err) - } - r.logger.Debug(context.Background(), "extracted directory", slog.F("path", headerPath)) - case tar.TypeReg: - file, err := r.filesystem.OpenFile(headerPath, os.O_CREATE|os.O_RDWR, mode) - if err != nil { - return nil, r.failedJobf("create file %q (mode %s): %s", headerPath, mode, err) - } - // Max file size of 10MiB. - size, err := io.CopyN(file, reader, 10<<20) - if errors.Is(err, io.EOF) { - err = nil - } - if err != nil { - _ = file.Close() - return nil, r.failedJobf("copy file %q: %s", headerPath, err) - } - err = file.Close() - if err != nil { - return nil, r.failedJobf("close file %q: %s", headerPath, err) - } - r.logger.Debug(context.Background(), "extracted file", - slog.F("size_bytes", size), - slog.F("path", headerPath), - slog.F("mode", mode), - ) - } - } switch jobType := r.job.Type.(type) { case *proto.AcquiredJob_TemplateImport_: r.logger.Debug(context.Background(), "acquired job is template import", slog.F("user_variable_values", redactVariableValues(jobType.TemplateImport.UserVariableValues)), ) - failedJob := r.runReadmeParse(ctx) - if failedJob != nil { - return nil, failedJob - } return r.runTemplateImport(ctx) case *proto.AcquiredJob_TemplateDryRun_: r.logger.Debug(context.Background(), "acquired job is template dry-run", @@ -525,6 +439,15 @@ func (r *Runner) do(ctx context.Context) (*proto.CompletedJob, *proto.FailedJob) } } +func (r *Runner) configure(config *sdkproto.Config) *proto.FailedJob { + var err error + err = r.session.Send(&sdkproto.Request{Type: &sdkproto.Request_Config{Config: config}}) + if err != nil { + return r.failedJobf("send config: %s", err) + } + return nil +} + // heartbeatRoutine periodically sends updates on the job, which keeps coder server // from assuming the job is stalled, and allows the runner to learn if the job // has been canceled by the user. @@ -577,44 +500,16 @@ func (r *Runner) heartbeatRoutine(ctx context.Context) { } } -// ReadmeFile is the location we look for to extract documentation from template -// versions. -const ReadmeFile = "README.md" - -func (r *Runner) runReadmeParse(ctx context.Context) *proto.FailedJob { +func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *proto.FailedJob) { ctx, span := r.startTrace(ctx, tracing.FuncName()) defer span.End() - fi, err := afero.ReadFile(r.filesystem, path.Join(r.workDirectory, ReadmeFile)) - if err != nil { - r.queueLog(ctx, &proto.Log{ - Source: proto.LogSource_PROVISIONER_DAEMON, - Level: sdkproto.LogLevel_DEBUG, - Stage: "No README.md provided", - CreatedAt: time.Now().UnixMilli(), - }) - return nil - } - - _, err = r.update(ctx, &proto.UpdateJobRequest{ - JobId: r.job.JobId, - Logs: []*proto.Log{{ - Source: proto.LogSource_PROVISIONER_DAEMON, - Level: sdkproto.LogLevel_INFO, - Stage: "Adding README.md...", - CreatedAt: time.Now().UnixMilli(), - }}, - Readme: fi, + failedJob := r.configure(&sdkproto.Config{ + TemplateSourceArchive: r.job.GetTemplateSourceArchive(), }) - if err != nil { - return r.failedJobf("write log: %s", err) + if failedJob != nil { + return nil, failedJob } - return nil -} - -func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *proto.FailedJob) { - ctx, span := r.startTrace(ctx, tracing.FuncName()) - defer span.End() // Parse parameters and update the job with the parameter specs r.queueLog(ctx, &proto.Log{ @@ -623,7 +518,7 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p Stage: "Parsing template parameters", CreatedAt: time.Now().UnixMilli(), }) - templateVariables, err := r.runTemplateImportParse(ctx) + templateVariables, readme, err := r.runTemplateImportParse(ctx) if err != nil { return nil, r.failedJobf("run parse: %s", err) } @@ -634,6 +529,7 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p JobId: r.job.JobId, TemplateVariables: templateVariables, UserVariableValues: r.job.GetTemplateImport().GetUserVariableValues(), + Readme: readme, }) if err != nil { return nil, r.failedJobf("update job: %s", err) @@ -646,7 +542,7 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p Stage: "Detecting persistent resources", CreatedAt: time.Now().UnixMilli(), }) - startProvision, err := r.runTemplateImportProvision(ctx, updateResponse.VariableValues, &sdkproto.Provision_Metadata{ + startProvision, err := r.runTemplateImportProvision(ctx, updateResponse.VariableValues, &sdkproto.Metadata{ CoderUrl: r.job.GetTemplateImport().Metadata.CoderUrl, WorkspaceTransition: sdkproto.WorkspaceTransition_START, }) @@ -661,7 +557,7 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p Stage: "Detecting ephemeral resources", CreatedAt: time.Now().UnixMilli(), }) - stopProvision, err := r.runTemplateImportProvision(ctx, updateResponse.VariableValues, &sdkproto.Provision_Metadata{ + stopProvision, err := r.runTemplateImportProvision(ctx, updateResponse.VariableValues, &sdkproto.Metadata{ CoderUrl: r.job.GetTemplateImport().Metadata.CoderUrl, WorkspaceTransition: sdkproto.WorkspaceTransition_STOP, }) @@ -682,25 +578,24 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p }, nil } -// Parses template variables and parameter schemas from source. -func (r *Runner) runTemplateImportParse(ctx context.Context) ([]*sdkproto.TemplateVariable, error) { +// Parses template variables and README from source. +func (r *Runner) runTemplateImportParse(ctx context.Context) ( + vars []*sdkproto.TemplateVariable, readme []byte, err error, +) { ctx, span := r.startTrace(ctx, tracing.FuncName()) defer span.End() - stream, err := r.provisioner.Parse(ctx, &sdkproto.Parse_Request{ - Directory: r.workDirectory, - }) + err = r.session.Send(&sdkproto.Request{Type: &sdkproto.Request_Parse{Parse: &sdkproto.ParseRequest{}}}) if err != nil { - return nil, xerrors.Errorf("parse source: %w", err) + return nil, nil, xerrors.Errorf("parse source: %w", err) } - defer stream.Close() for { - msg, err := stream.Recv() + msg, err := r.session.Recv() if err != nil { - return nil, xerrors.Errorf("recv parse source: %w", err) + return nil, nil, xerrors.Errorf("recv parse source: %w", err) } switch msgType := msg.Type.(type) { - case *sdkproto.Parse_Response_Log: + case *sdkproto.Response_Log: r.logger.Debug(context.Background(), "parse job logged", slog.F("level", msgType.Log.Level), slog.F("output", msgType.Log.Output), @@ -713,14 +608,20 @@ func (r *Runner) runTemplateImportParse(ctx context.Context) ([]*sdkproto.Templa Output: msgType.Log.Output, Stage: "Parse parameters", }) - case *sdkproto.Parse_Response_Complete: + case *sdkproto.Response_Parse: + pc := msgType.Parse r.logger.Debug(context.Background(), "parse complete", - slog.F("template_variables", msgType.Complete.TemplateVariables), + slog.F("template_variables", pc.TemplateVariables), + slog.F("readme_len", len(pc.Readme)), + slog.F("error", pc.Error), ) + if pc.Error != "" { + return nil, nil, xerrors.Errorf("parse error: %s", pc.Error) + } - return msgType.Complete.TemplateVariables, nil + return msgType.Parse.TemplateVariables, msgType.Parse.Readme, nil default: - return nil, xerrors.Errorf("invalid message type %q received from provisioner", + return nil, nil, xerrors.Errorf("invalid message type %q received from provisioner", reflect.TypeOf(msg.Type).String()) } } @@ -735,13 +636,18 @@ 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.Provision_Metadata) (*templateImportProvision, error) { +func (r *Runner) runTemplateImportProvision(ctx context.Context, variableValues []*sdkproto.VariableValue, metadata *sdkproto.Metadata) (*templateImportProvision, error) { return r.runTemplateImportProvisionWithRichParameters(ctx, variableValues, nil, metadata) } // Performs a dry-run provision with provided rich parameters. // This is used to detect resources that would be provisioned for a workspace in various states. -func (r *Runner) runTemplateImportProvisionWithRichParameters(ctx context.Context, variableValues []*sdkproto.VariableValue, richParameterValues []*sdkproto.RichParameterValue, metadata *sdkproto.Provision_Metadata) (*templateImportProvision, error) { +func (r *Runner) runTemplateImportProvisionWithRichParameters( + ctx context.Context, + variableValues []*sdkproto.VariableValue, + richParameterValues []*sdkproto.RichParameterValue, + metadata *sdkproto.Metadata, +) (*templateImportProvision, error) { ctx, span := r.startTrace(ctx, tracing.FuncName()) defer span.End() @@ -754,46 +660,38 @@ func (r *Runner) runTemplateImportProvisionWithRichParameters(ctx context.Contex } // use the notStopped so that if we attempt to gracefully cancel, the stream will still be available for us // to send the cancel to the provisioner - stream, err := r.provisioner.Provision(ctx) + err := r.session.Send(&sdkproto.Request{Type: &sdkproto.Request_Plan{Plan: &sdkproto.PlanRequest{ + Metadata: metadata, + RichParameterValues: richParameterValues, + VariableValues: variableValues, + }}}) if err != nil { - return nil, xerrors.Errorf("provision: %w", err) + return nil, xerrors.Errorf("start provision: %w", err) } - defer stream.Close() + nevermind := make(chan struct{}) + defer close(nevermind) go func() { select { + case <-nevermind: + return case <-r.notStopped.Done(): return case <-r.notCanceled.Done(): - _ = stream.Send(&sdkproto.Provision_Request{ - Type: &sdkproto.Provision_Request_Cancel{ - Cancel: &sdkproto.Provision_Cancel{}, + _ = r.session.Send(&sdkproto.Request{ + Type: &sdkproto.Request_Cancel{ + Cancel: &sdkproto.CancelRequest{}, }, }) } }() - err = stream.Send(&sdkproto.Provision_Request{ - Type: &sdkproto.Provision_Request_Plan{ - Plan: &sdkproto.Provision_Plan{ - Config: &sdkproto.Provision_Config{ - Directory: r.workDirectory, - Metadata: metadata, - }, - RichParameterValues: richParameterValues, - VariableValues: variableValues, - }, - }, - }) - if err != nil { - return nil, xerrors.Errorf("start provision: %w", err) - } for { - msg, err := stream.Recv() + msg, err := r.session.Recv() if err != nil { return nil, xerrors.Errorf("recv import provision: %w", err) } switch msgType := msg.Type.(type) { - case *sdkproto.Provision_Response_Log: + case *sdkproto.Response_Log: r.logger.Debug(context.Background(), "template import provision job logged", slog.F("level", msgType.Log.Level), slog.F("output", msgType.Log.Output), @@ -805,25 +703,25 @@ func (r *Runner) runTemplateImportProvisionWithRichParameters(ctx context.Contex Output: msgType.Log.Output, Stage: stage, }) - case *sdkproto.Provision_Response_Complete: - if msgType.Complete.Error != "" { + case *sdkproto.Response_Plan: + c := msgType.Plan + if c.Error != "" { r.logger.Info(context.Background(), "dry-run provision failure", - slog.F("error", msgType.Complete.Error), + slog.F("error", c.Error), ) - return nil, xerrors.New(msgType.Complete.Error) + return nil, xerrors.New(c.Error) } r.logger.Info(context.Background(), "parse dry-run provision successful", - slog.F("resource_count", len(msgType.Complete.Resources)), - slog.F("resources", msgType.Complete.Resources), - slog.F("state_length", len(msgType.Complete.State)), + slog.F("resource_count", len(c.Resources)), + slog.F("resources", c.Resources), ) return &templateImportProvision{ - Resources: msgType.Complete.Resources, - Parameters: msgType.Complete.Parameters, - GitAuthProviders: msgType.Complete.GitAuthProviders, + Resources: c.Resources, + Parameters: c.Parameters, + GitAuthProviders: c.GitAuthProviders, }, nil default: return nil, xerrors.Errorf("invalid message type %q received from provisioner", @@ -864,6 +762,13 @@ func (r *Runner) runTemplateDryRun(ctx context.Context) (*proto.CompletedJob, *p metadata.WorkspaceOwnerId = id.String() } + failedJob := r.configure(&sdkproto.Config{ + TemplateSourceArchive: r.job.GetTemplateSourceArchive(), + }) + if failedJob != nil { + return nil, failedJob + } + // Run the template import provision task since it's already a dry run. provision, err := r.runTemplateImportProvisionWithRichParameters(ctx, r.job.GetTemplateDryRun().GetVariableValues(), @@ -884,41 +789,39 @@ func (r *Runner) runTemplateDryRun(ctx context.Context) (*proto.CompletedJob, *p }, nil } -func (r *Runner) buildWorkspace(ctx context.Context, stage string, req *sdkproto.Provision_Request) ( - *sdkproto.Provision_Complete, *proto.FailedJob, +func (r *Runner) buildWorkspace(ctx context.Context, stage string, req *sdkproto.Request) ( + *sdkproto.Response, *proto.FailedJob, ) { // use the notStopped so that if we attempt to gracefully cancel, the stream // will still be available for us to send the cancel to the provisioner - stream, err := r.provisioner.Provision(ctx) + err := r.session.Send(req) if err != nil { - return nil, r.failedWorkspaceBuildf("provision: %s", err) + return nil, r.failedWorkspaceBuildf("start provision: %s", err) } - defer stream.Close() + nevermind := make(chan struct{}) + defer close(nevermind) go func() { select { + case <-nevermind: + return case <-r.notStopped.Done(): return case <-r.notCanceled.Done(): - _ = stream.Send(&sdkproto.Provision_Request{ - Type: &sdkproto.Provision_Request_Cancel{ - Cancel: &sdkproto.Provision_Cancel{}, + _ = r.session.Send(&sdkproto.Request{ + Type: &sdkproto.Request_Cancel{ + Cancel: &sdkproto.CancelRequest{}, }, }) } }() - err = stream.Send(req) - if err != nil { - return nil, r.failedWorkspaceBuildf("start provision: %s", err) - } - for { - msg, err := stream.Recv() + msg, err := r.session.Recv() if err != nil { return nil, r.failedWorkspaceBuildf("recv workspace provision: %s", err) } switch msgType := msg.Type.(type) { - case *sdkproto.Provision_Response_Log: + case *sdkproto.Response_Log: r.logProvisionerJobLog(context.Background(), msgType.Log.Level, "workspace provisioner job logged", slog.F("level", msgType.Log.Level), slog.F("output", msgType.Log.Output), @@ -932,33 +835,9 @@ func (r *Runner) buildWorkspace(ctx context.Context, stage string, req *sdkproto Output: msgType.Log.Output, Stage: stage, }) - case *sdkproto.Provision_Response_Complete: - if msgType.Complete.Error != "" { - r.logger.Warn(context.Background(), "provision failed; updating state", - slog.F("state_length", len(msgType.Complete.State)), - slog.F("error", msgType.Complete.Error), - ) - - return nil, &proto.FailedJob{ - JobId: r.job.JobId, - Error: msgType.Complete.Error, - Type: &proto.FailedJob_WorkspaceBuild_{ - WorkspaceBuild: &proto.FailedJob_WorkspaceBuild{ - State: msgType.Complete.State, - }, - }, - } - } - - r.logger.Info(context.Background(), "provision successful", - slog.F("resource_count", len(msgType.Complete.Resources)), - slog.F("resources", msgType.Complete.Resources), - slog.F("state_length", len(msgType.Complete.State)), - ) - // Stop looping! - return msgType.Complete, nil default: - return nil, r.failedWorkspaceBuildf("invalid message type %T received from provisioner", msg.Type) + // Stop looping! + return msg, nil } } } @@ -1035,18 +914,19 @@ func (r *Runner) runWorkspaceBuild(ctx context.Context) (*proto.CompletedJob, *p applyStage = "Destroying workspace" } - config := &sdkproto.Provision_Config{ - Directory: r.workDirectory, - Metadata: r.job.GetWorkspaceBuild().Metadata, - State: r.job.GetWorkspaceBuild().State, - - ProvisionerLogLevel: r.job.GetWorkspaceBuild().LogLevel, + failedJob := r.configure(&sdkproto.Config{ + TemplateSourceArchive: r.job.GetTemplateSourceArchive(), + State: r.job.GetWorkspaceBuild().State, + ProvisionerLogLevel: r.job.GetWorkspaceBuild().LogLevel, + }) + if failedJob != nil { + return nil, failedJob } - completedPlan, failed := r.buildWorkspace(ctx, "Planning infrastructure", &sdkproto.Provision_Request{ - Type: &sdkproto.Provision_Request_Plan{ - Plan: &sdkproto.Provision_Plan{ - Config: config, + resp, failed := r.buildWorkspace(ctx, "Planning infrastructure", &sdkproto.Request{ + Type: &sdkproto.Request_Plan{ + Plan: &sdkproto.PlanRequest{ + Metadata: r.job.GetWorkspaceBuild().Metadata, RichParameterValues: r.job.GetWorkspaceBuild().RichParameterValues, VariableValues: r.job.GetWorkspaceBuild().VariableValues, GitAuthProviders: r.job.GetWorkspaceBuild().GitAuthProviders, @@ -1056,9 +936,31 @@ func (r *Runner) runWorkspaceBuild(ctx context.Context) (*proto.CompletedJob, *p if failed != nil { return nil, failed } + planComplete := resp.GetPlan() + if planComplete == nil { + return nil, r.failedWorkspaceBuildf("invalid message type %T received from provisioner", resp.Type) + } + if planComplete.Error != "" { + r.logger.Warn(context.Background(), "plan failed", + slog.F("error", planComplete.Error), + ) + + return nil, &proto.FailedJob{ + JobId: r.job.JobId, + Error: planComplete.Error, + Type: &proto.FailedJob_WorkspaceBuild_{ + WorkspaceBuild: &proto.FailedJob_WorkspaceBuild{}, + }, + } + } + + r.logger.Info(context.Background(), "plan successful", + slog.F("resource_count", len(planComplete.Resources)), + slog.F("resources", planComplete.Resources), + ) r.flushQueuedLogs(ctx) if commitQuota { - failed = r.commitQuota(ctx, completedPlan.GetResources()) + failed = r.commitQuota(ctx, planComplete.Resources) r.flushQueuedLogs(ctx) if failed != nil { return nil, failed @@ -1072,25 +974,50 @@ func (r *Runner) runWorkspaceBuild(ctx context.Context) (*proto.CompletedJob, *p CreatedAt: time.Now().UnixMilli(), }) - completedApply, failed := r.buildWorkspace(ctx, applyStage, &sdkproto.Provision_Request{ - Type: &sdkproto.Provision_Request_Apply{ - Apply: &sdkproto.Provision_Apply{ - Config: config, - Plan: completedPlan.GetPlan(), + resp, failed = r.buildWorkspace(ctx, applyStage, &sdkproto.Request{ + Type: &sdkproto.Request_Apply{ + Apply: &sdkproto.ApplyRequest{ + Metadata: r.job.GetWorkspaceBuild().Metadata, }, }, }) if failed != nil { return nil, failed } + applyComplete := resp.GetApply() + if applyComplete == nil { + return nil, r.failedWorkspaceBuildf("invalid message type %T received from provisioner", resp.Type) + } + if applyComplete.Error != "" { + r.logger.Warn(context.Background(), "apply failed; updating state", + slog.F("error", applyComplete.Error), + slog.F("state_len", len(applyComplete.State)), + ) + + return nil, &proto.FailedJob{ + JobId: r.job.JobId, + Error: applyComplete.Error, + Type: &proto.FailedJob_WorkspaceBuild_{ + WorkspaceBuild: &proto.FailedJob_WorkspaceBuild{ + State: applyComplete.State, + }, + }, + } + } + + r.logger.Info(context.Background(), "apply successful", + slog.F("resource_count", len(applyComplete.Resources)), + slog.F("resources", applyComplete.Resources), + slog.F("state_len", len(applyComplete.State)), + ) r.flushQueuedLogs(ctx) return &proto.CompletedJob{ JobId: r.job.JobId, Type: &proto.CompletedJob_WorkspaceBuild_{ WorkspaceBuild: &proto.CompletedJob_WorkspaceBuild{ - State: completedApply.GetState(), - Resources: completedApply.GetResources(), + State: applyComplete.State, + Resources: applyComplete.Resources, }, }, }, nil From 2be6cf0a6241cbcbcb27294747737c909c3fdb7d Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Wed, 23 Aug 2023 08:32:43 +0000 Subject: [PATCH 04/13] refactor tests & proto renames --- cli/agent_test.go | 18 +-- cli/configssh_test.go | 21 +--- cli/create_test.go | 95 +++++---------- cli/gitssh_test.go | 2 +- cli/portforward_test.go | 2 +- cli/restart_test.go | 42 ++----- cli/show_test.go | 7 +- cli/ssh_test.go | 8 +- cli/start_test.go | 24 ++-- cli/state_test.go | 16 +-- cli/templatecreate_test.go | 77 +++++++------ cli/templatepull_test.go | 10 +- cli/templatepush_test.go | 31 +++-- cli/update_test.go | 55 ++------- coderd/activitybump_test.go | 23 +--- coderd/autobuild/lifecycle_executor_test.go | 22 ++-- coderd/gitauth_test.go | 30 ++--- coderd/gitsshkey_test.go | 2 +- coderd/insights_test.go | 16 +-- .../prometheusmetrics_test.go | 10 +- .../provisionerdserver/provisionerdserver.go | 6 +- .../provisionerdserver_test.go | 8 +- coderd/provisionerjobs_test.go | 16 +-- coderd/templates_test.go | 2 +- coderd/templateversions_test.go | 88 +++++++------- coderd/workspaceagents_test.go | 88 +++++++------- coderd/workspaceapps/apptest/setup.go | 8 +- coderd/workspaceapps/db_test.go | 8 +- coderd/workspacebuilds_test.go | 65 ++++++----- coderd/workspaceresourceauth_test.go | 18 +-- coderd/workspaces_test.go | 108 +++++++++--------- enterprise/coderd/appearance_test.go | 2 +- enterprise/coderd/provisionerdaemons_test.go | 6 +- enterprise/coderd/workspaceagents_test.go | 6 +- enterprise/coderd/workspacequota_test.go | 70 ++++++------ enterprise/coderd/workspaces_test.go | 40 +++---- scaletest/agentconn/run_test.go | 8 +- scaletest/createworkspaces/run_test.go | 34 +++--- scaletest/reconnectingpty/run_test.go | 8 +- scaletest/workspacebuild/run_test.go | 18 +-- scaletest/workspacetraffic/run_test.go | 16 +-- 41 files changed, 492 insertions(+), 642 deletions(-) diff --git a/cli/agent_test.go b/cli/agent_test.go index d33bb55d00b2f..7073f7c0f18ca 100644 --- a/cli/agent_test.go +++ b/cli/agent_test.go @@ -75,9 +75,9 @@ func TestWorkspaceAgent(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "somename", Type: "someinstance", @@ -127,9 +127,9 @@ func TestWorkspaceAgent(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "somename", Type: "someinstance", @@ -179,9 +179,9 @@ func TestWorkspaceAgent(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "somename", Type: "someinstance", diff --git a/cli/configssh_test.go b/cli/configssh_test.go index a592efa424300..44246da2596e7 100644 --- a/cli/configssh_test.go +++ b/cli/configssh_test.go @@ -82,9 +82,9 @@ func TestConfigSSH(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: []*proto.Response{{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -720,22 +720,11 @@ func TestConfigSSH_Hostnames(t *testing.T) { resources = append(resources, resource) } - provisionResponse := []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Resources: resources, - }, - }, - }} - client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) user := coderdtest.CreateFirstUser(t, client) // authToken := uuid.NewString() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: provisionResponse, - ProvisionApply: provisionResponse, - }) + version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, + echo.WithResources(resources)) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) diff --git a/cli/create_test.go b/cli/create_test.go index f3436c0268f3d..bdd229775ec68 100644 --- a/cli/create_test.go +++ b/cli/create_test.go @@ -29,11 +29,7 @@ func TestCreate(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) user := coderdtest.CreateFirstUser(t, client) - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: provisionCompleteWithAgent, - ProvisionPlan: provisionCompleteWithAgent, - }) + version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, completeWithAgent()) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) args := []string{ @@ -84,11 +80,7 @@ func TestCreate(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) - version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: provisionCompleteWithAgent, - ProvisionPlan: provisionCompleteWithAgent, - }) + version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, completeWithAgent()) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID) _, user := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) @@ -141,11 +133,7 @@ func TestCreate(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) user := coderdtest.CreateFirstUser(t, client) - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: provisionCompleteWithAgent, - ProvisionPlan: provisionCompleteWithAgent, - }) + version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, completeWithAgent()) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { var defaultTTLMillis int64 = 2 * 60 * 60 * 1000 // 2 hours @@ -240,6 +228,22 @@ func TestCreate(t *testing.T) { }) } +func prepareEchoResponses(parameters []*proto.RichParameter) *echo.Responses { + return &echo.Responses{ + Parse: echo.ParseComplete, + ProvisionPlan: []*proto.Response{ + { + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ + Parameters: parameters, + }, + }, + }, + }, + ProvisionApply: echo.ApplyComplete, + } +} + func TestCreateWithRichParameters(t *testing.T) { t.Parallel() @@ -258,27 +262,12 @@ func TestCreateWithRichParameters(t *testing.T) { immutableParameterValue = "4" ) - echoResponses := &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{ - { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Parameters: []*proto.RichParameter{ - {Name: firstParameterName, Description: firstParameterDescription, Mutable: true}, - {Name: secondParameterName, DisplayName: secondParameterDisplayName, Description: secondParameterDescription, Mutable: true}, - {Name: immutableParameterName, Description: immutableParameterDescription, Mutable: false}, - }, - }, - }, - }, - }, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, - }, - }}, - } + echoResponses := prepareEchoResponses([]*proto.RichParameter{ + {Name: firstParameterName, Description: firstParameterDescription, Mutable: true}, + {Name: secondParameterName, DisplayName: secondParameterDisplayName, Description: secondParameterDescription, Mutable: true}, + {Name: immutableParameterName, Description: immutableParameterDescription, Mutable: false}, + }, + ) t.Run("InputParameters", func(t *testing.T) { t.Parallel() @@ -427,28 +416,6 @@ func TestCreateValidateRichParameters(t *testing.T) { {Name: boolParameterName, Type: "bool", Mutable: true}, } - prepareEchoResponses := func(richParameters []*proto.RichParameter) *echo.Responses { - return &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{ - { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Parameters: richParameters, - }, - }, - }, - }, - ProvisionApply: []*proto.Provision_Response{ - { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, - }, - }, - }, - } - } - t.Run("ValidateString", func(t *testing.T) { t.Parallel() @@ -626,20 +593,16 @@ func TestCreateWithGitAuth(t *testing.T) { t.Parallel() echoResponses := &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{ + ProvisionPlan: []*proto.Response{ { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ GitAuthProviders: []string{"github"}, }, }, }, }, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, - }, - }}, + ProvisionApply: echo.ApplyComplete, } client := coderdtest.New(t, &coderdtest.Options{ diff --git a/cli/gitssh_test.go b/cli/gitssh_test.go index 9c38ef945ba7b..3e5045acf0288 100644 --- a/cli/gitssh_test.go +++ b/cli/gitssh_test.go @@ -48,7 +48,7 @@ func prepareTestGitSSH(ctx context.Context, t *testing.T) (*codersdk.Client, str agentToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(agentToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) diff --git a/cli/portforward_test.go b/cli/portforward_test.go index ce480768525f2..030133a7ae317 100644 --- a/cli/portforward_test.go +++ b/cli/portforward_test.go @@ -302,7 +302,7 @@ func runAgent(t *testing.T, client *codersdk.Client, userID uuid.UUID) codersdk. agentToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, orgID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(agentToken), }) diff --git a/cli/restart_test.go b/cli/restart_test.go index b68a3f843ba51..43b512c1bc30b 100644 --- a/cli/restart_test.go +++ b/cli/restart_test.go @@ -20,30 +20,14 @@ import ( func TestRestart(t *testing.T) { t.Parallel() - echoResponses := &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{ - { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Parameters: []*proto.RichParameter{ - { - Name: ephemeralParameterName, - Description: ephemeralParameterDescription, - Mutable: true, - Ephemeral: true, - }, - }, - }, - }, - }, + echoResponses := prepareEchoResponses([]*proto.RichParameter{ + { + Name: ephemeralParameterName, + Description: ephemeralParameterDescription, + Mutable: true, + Ephemeral: true, }, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, - }, - }}, - } + }) t.Run("OK", func(t *testing.T) { t.Parallel() @@ -187,10 +171,10 @@ func TestRestartWithParameters(t *testing.T) { echoResponses := &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{ + ProvisionPlan: []*proto.Response{ { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ Parameters: []*proto.RichParameter{ { Name: immutableParameterName, @@ -202,11 +186,7 @@ func TestRestartWithParameters(t *testing.T) { }, }, }, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, - }, - }}, + ProvisionApply: echo.ApplyComplete, } t.Run("DoNotAskForImmutables", func(t *testing.T) { diff --git a/cli/show_test.go b/cli/show_test.go index c77e5dc0171cb..ccbe182cc7ed9 100644 --- a/cli/show_test.go +++ b/cli/show_test.go @@ -7,7 +7,6 @@ import ( "github.com/coder/coder/v2/cli/clitest" "github.com/coder/coder/v2/coderd/coderdtest" - "github.com/coder/coder/v2/provisioner/echo" "github.com/coder/coder/v2/pty/ptytest" ) @@ -17,11 +16,7 @@ func TestShow(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) user := coderdtest.CreateFirstUser(t, client) - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: provisionCompleteWithAgent, - ProvisionPlan: provisionCompleteWithAgent, - }) + version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, completeWithAgent()) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) diff --git a/cli/ssh_test.go b/cli/ssh_test.go index 5e670d44d0689..971dc2873ffdc 100644 --- a/cli/ssh_test.go +++ b/cli/ssh_test.go @@ -56,10 +56,10 @@ func setupWorkspaceForAgent(t *testing.T, mutate func([]*proto.Agent) []*proto.A agentToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "dev", Type: "google_compute_instance", diff --git a/cli/start_test.go b/cli/start_test.go index e92d70cd71624..dff4048f3e765 100644 --- a/cli/start_test.go +++ b/cli/start_test.go @@ -33,10 +33,10 @@ func TestStart(t *testing.T) { echoResponses := &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{ + ProvisionPlan: []*proto.Response{ { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ Parameters: []*proto.RichParameter{ { Name: ephemeralParameterName, @@ -49,11 +49,7 @@ func TestStart(t *testing.T) { }, }, }, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, - }, - }}, + ProvisionApply: echo.ApplyComplete, } t.Run("BuildOptions", func(t *testing.T) { @@ -151,10 +147,10 @@ func TestStartWithParameters(t *testing.T) { echoResponses := &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{ + ProvisionPlan: []*proto.Response{ { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ Parameters: []*proto.RichParameter{ { Name: immutableParameterName, @@ -166,11 +162,7 @@ func TestStartWithParameters(t *testing.T) { }, }, }, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, - }, - }}, + ProvisionApply: echo.ApplyComplete, } t.Run("DoNotAskForImmutables", func(t *testing.T) { diff --git a/cli/state_test.go b/cli/state_test.go index 6273135d39c84..a240a6d2c81ae 100644 --- a/cli/state_test.go +++ b/cli/state_test.go @@ -25,9 +25,9 @@ func TestStatePull(t *testing.T) { wantState := []byte("some state") version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ State: wantState, }, }, @@ -53,9 +53,9 @@ func TestStatePull(t *testing.T) { wantState := []byte("some state") version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ State: wantState, }, }, @@ -83,7 +83,7 @@ func TestStatePush(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionApply: echo.ApplyComplete, }) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -108,7 +108,7 @@ func TestStatePush(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionApply: echo.ApplyComplete, }) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) diff --git a/cli/templatecreate_test.go b/cli/templatecreate_test.go index 1c3d6d6c954bc..ba5dad7b4ac6a 100644 --- a/cli/templatecreate_test.go +++ b/cli/templatecreate_test.go @@ -19,26 +19,52 @@ import ( "github.com/coder/coder/v2/testutil" ) -var provisionCompleteWithAgent = []*proto.Provision_Response{ - { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Resources: []*proto.Resource{ - { - Type: "compute", - Name: "main", - Agents: []*proto.Agent{ +func completeWithAgent() *echo.Responses { + return &echo.Responses{ + Parse: echo.ParseComplete, + ProvisionPlan: []*proto.Response{ + { + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ + Resources: []*proto.Resource{ + { + Type: "compute", + Name: "main", + Agents: []*proto.Agent{ + { + Name: "smith", + OperatingSystem: "linux", + Architecture: "i386", + }, + }, + }, + }, + }, + }, + }, + }, + ProvisionApply: []*proto.Response{ + { + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ + Resources: []*proto.Resource{ { - Name: "smith", - OperatingSystem: "linux", - Architecture: "i386", + Type: "compute", + Name: "main", + Agents: []*proto.Agent{ + { + Name: "smith", + OperatingSystem: "linux", + Architecture: "i386", + }, + }, }, }, }, }, }, }, - }, + } } func TestTemplateCreate(t *testing.T) { @@ -47,10 +73,7 @@ func TestTemplateCreate(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) coderdtest.CreateFirstUser(t, client) - source := clitest.CreateTemplateVersionSource(t, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: provisionCompleteWithAgent, - }) + source := clitest.CreateTemplateVersionSource(t, completeWithAgent()) args := []string{ "templates", "create", @@ -85,10 +108,7 @@ func TestTemplateCreate(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) coderdtest.CreateFirstUser(t, client) - source := clitest.CreateTemplateVersionSource(t, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: provisionCompleteWithAgent, - }) + source := clitest.CreateTemplateVersionSource(t, completeWithAgent()) require.NoError(t, os.Remove(filepath.Join(source, ".terraform.lock.hcl"))) args := []string{ "templates", @@ -128,10 +148,7 @@ func TestTemplateCreate(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) coderdtest.CreateFirstUser(t, client) - source := clitest.CreateTemplateVersionSource(t, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: provisionCompleteWithAgent, - }) + source := clitest.CreateTemplateVersionSource(t, completeWithAgent()) require.NoError(t, os.Remove(filepath.Join(source, ".terraform.lock.hcl"))) args := []string{ "templates", @@ -167,10 +184,7 @@ func TestTemplateCreate(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) coderdtest.CreateFirstUser(t, client) - source, err := echo.Tar(&echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: provisionCompleteWithAgent, - }) + source, err := echo.Tar(completeWithAgent()) require.NoError(t, err) args := []string{ @@ -196,10 +210,7 @@ func TestTemplateCreate(t *testing.T) { coderdtest.CreateFirstUser(t, client) create := func() error { - source := clitest.CreateTemplateVersionSource(t, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: provisionCompleteWithAgent, - }) + source := clitest.CreateTemplateVersionSource(t, completeWithAgent()) args := []string{ "templates", "create", diff --git a/cli/templatepull_test.go b/cli/templatepull_test.go index f6d8ececc9356..95b0a6cf9aa30 100644 --- a/cli/templatepull_test.go +++ b/cli/templatepull_test.go @@ -205,9 +205,9 @@ func TestTemplatePull(t *testing.T) { // a template version source. func genTemplateVersionSource() *echo.Responses { return &echo.Responses{ - Parse: []*proto.Parse_Response{ + Parse: []*proto.Response{ { - Type: &proto.Parse_Response_Log{ + Type: &proto.Response_Log{ Log: &proto.Log{ Output: uuid.NewString(), }, @@ -215,11 +215,11 @@ func genTemplateVersionSource() *echo.Responses { }, { - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{}, + Type: &proto.Response_Parse{ + Parse: &proto.ParseComplete{}, }, }, }, - ProvisionApply: echo.ProvisionComplete, + ProvisionApply: echo.ApplyComplete, } } diff --git a/cli/templatepush_test.go b/cli/templatepush_test.go index 4f2e00a359be2..4c41597802bb2 100644 --- a/cli/templatepush_test.go +++ b/cli/templatepush_test.go @@ -38,7 +38,7 @@ func TestTemplatePush(t *testing.T) { // Test the cli command. source := clitest.CreateTemplateVersionSource(t, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionApply: echo.ApplyComplete, }) inv, root := clitest.New(t, "templates", "push", template.Name, "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--name", "example") clitest.SetupConfig(t, client, root) @@ -82,7 +82,7 @@ func TestTemplatePush(t *testing.T) { template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) source := clitest.CreateTemplateVersionSource(t, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionApply: echo.ApplyComplete, }) wantMessage := strings.Repeat("a", 72) @@ -121,7 +121,7 @@ func TestTemplatePush(t *testing.T) { template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) source := clitest.CreateTemplateVersionSource(t, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionApply: echo.ApplyComplete, }) ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) @@ -168,7 +168,7 @@ func TestTemplatePush(t *testing.T) { // Test the cli command. source := clitest.CreateTemplateVersionSource(t, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionApply: echo.ApplyComplete, }) require.NoError(t, os.Remove(filepath.Join(source, ".terraform.lock.hcl"))) @@ -211,7 +211,7 @@ func TestTemplatePush(t *testing.T) { // Test the cli command. source := clitest.CreateTemplateVersionSource(t, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionApply: echo.ApplyComplete, }) require.NoError(t, os.Remove(filepath.Join(source, ".terraform.lock.hcl"))) @@ -248,7 +248,7 @@ func TestTemplatePush(t *testing.T) { // Test the cli command. source := clitest.CreateTemplateVersionSource(t, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionApply: echo.ApplyComplete, }) inv, root := clitest.New(t, "templates", "push", template.Name, "--activate=false", "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--name", "example") clitest.SetupConfig(t, client, root) @@ -293,7 +293,7 @@ func TestTemplatePush(t *testing.T) { // Test the cli command. source := clitest.CreateTemplateVersionSource(t, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionApply: echo.ApplyComplete, }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, @@ -340,7 +340,7 @@ func TestTemplatePush(t *testing.T) { source, err := echo.Tar(&echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionApply: echo.ApplyComplete, }) require.NoError(t, err) @@ -619,10 +619,7 @@ func TestTemplatePush(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) user := coderdtest.CreateFirstUser(t, client) - source := clitest.CreateTemplateVersionSource(t, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: provisionCompleteWithAgent, - }) + source := clitest.CreateTemplateVersionSource(t, completeWithAgent()) const templateName = "my-template" args := []string{ @@ -665,16 +662,16 @@ func TestTemplatePush(t *testing.T) { func createEchoResponsesWithTemplateVariables(templateVariables []*proto.TemplateVariable) *echo.Responses { return &echo.Responses{ - Parse: []*proto.Parse_Response{ + Parse: []*proto.Response{ { - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{ + Type: &proto.Response_Parse{ + Parse: &proto.ParseComplete{ TemplateVariables: templateVariables, }, }, }, }, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ApplyComplete, } } diff --git a/cli/update_test.go b/cli/update_test.go index e799557fcc454..b87f1aba8e76e 100644 --- a/cli/update_test.go +++ b/cli/update_test.go @@ -57,8 +57,8 @@ func TestUpdate(t *testing.T) { version2 := coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: echo.ProvisionComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionApply: echo.ApplyComplete, + ProvisionPlan: echo.PlanComplete, }, template.ID) _ = coderdtest.AwaitTemplateVersionJob(t, client, version2.ID) @@ -100,28 +100,13 @@ func TestUpdateWithRichParameters(t *testing.T) { immutableParameterValue = "4" ) - echoResponses := &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{ - { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Parameters: []*proto.RichParameter{ - {Name: firstParameterName, Description: firstParameterDescription, Mutable: true}, - {Name: immutableParameterName, Description: immutableParameterDescription, Mutable: false}, - {Name: secondParameterName, Description: secondParameterDescription, Mutable: true}, - {Name: ephemeralParameterName, Description: ephemeralParameterDescription, Mutable: true, Ephemeral: true}, - }, - }, - }, - }, - }, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, - }, - }}, - } + echoResponses := prepareEchoResponses([]*proto.RichParameter{ + {Name: firstParameterName, Description: firstParameterDescription, Mutable: true}, + {Name: immutableParameterName, Description: immutableParameterDescription, Mutable: false}, + {Name: secondParameterName, Description: secondParameterDescription, Mutable: true}, + {Name: ephemeralParameterName, Description: ephemeralParameterDescription, Mutable: true, Ephemeral: true}, + }, + ) t.Run("ImmutableCannotBeCustomized", func(t *testing.T) { t.Parallel() @@ -313,28 +298,6 @@ func TestUpdateValidateRichParameters(t *testing.T) { {Name: boolParameterName, Type: "bool", Mutable: true}, } - prepareEchoResponses := func(richParameters []*proto.RichParameter) *echo.Responses { - return &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{ - { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Parameters: richParameters, - }, - }, - }, - }, - ProvisionApply: []*proto.Provision_Response{ - { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, - }, - }, - }, - } - } - t.Run("ValidateString", func(t *testing.T) { t.Parallel() diff --git a/coderd/activitybump_test.go b/coderd/activitybump_test.go index 15965f5ab1fea..8ce018a4e9a20 100644 --- a/coderd/activitybump_test.go +++ b/coderd/activitybump_test.go @@ -17,7 +17,6 @@ import ( "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk/agentsdk" "github.com/coder/coder/v2/provisioner/echo" - "github.com/coder/coder/v2/provisionersdk/proto" "github.com/coder/coder/v2/testutil" ) @@ -60,25 +59,9 @@ func TestWorkspaceActivityBump(t *testing.T) { ttlMillis := int64(ttl / time.Millisecond) agentToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Resources: []*proto.Resource{{ - Name: "example", - Type: "aws_instance", - Agents: []*proto.Agent{{ - Id: uuid.NewString(), - Name: "agent", - Auth: &proto.Agent_Token{ - Token: agentToken, - }, - }}, - }}, - }, - }, - }}, + Parse: echo.ParseComplete, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ProvisionApplyWithAgent(agentToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) diff --git a/coderd/autobuild/lifecycle_executor_test.go b/coderd/autobuild/lifecycle_executor_test.go index b1b854167e4b2..3c92d46b98f7d 100644 --- a/coderd/autobuild/lifecycle_executor_test.go +++ b/coderd/autobuild/lifecycle_executor_test.go @@ -683,8 +683,8 @@ func TestExecutorFailedWorkspace(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: echo.ProvisionFailed, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ApplyFailed, }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { ctr.FailureTTLMillis = ptr.Ref[int64](failureTTL.Milliseconds()) @@ -733,8 +733,8 @@ func TestExecutorInactiveWorkspace(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ApplyComplete, }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { ctr.InactivityTTLMillis = ptr.Ref[int64](inactiveTTL.Milliseconds()) @@ -766,22 +766,16 @@ func mustProvisionWorkspaceWithParameters(t *testing.T, client *codersdk.Client, user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{ + ProvisionPlan: []*proto.Response{ { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ Parameters: richParameters, }, }, }, }, - ProvisionApply: []*proto.Provision_Response{ - { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, - }, - }, - }, + ProvisionApply: echo.ApplyComplete, }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) diff --git a/coderd/gitauth_test.go b/coderd/gitauth_test.go index 6aa4d4735b06f..c0ad89a1b53cc 100644 --- a/coderd/gitauth_test.go +++ b/coderd/gitauth_test.go @@ -23,7 +23,6 @@ import ( "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk/agentsdk" "github.com/coder/coder/v2/provisioner/echo" - "github.com/coder/coder/v2/provisionersdk/proto" "github.com/coder/coder/v2/testutil" ) @@ -227,7 +226,7 @@ func TestGitAuthCallback(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -256,24 +255,9 @@ func TestGitAuthCallback(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Resources: []*proto.Resource{{ - Name: "example", - Type: "aws_instance", - Agents: []*proto.Agent{{ - Id: uuid.NewString(), - Auth: &proto.Agent_Token{ - Token: authToken, - }, - }}, - }}, - }, - }, - }}, + Parse: echo.ParseComplete, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) @@ -342,7 +326,7 @@ func TestGitAuthCallback(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -400,7 +384,7 @@ func TestGitAuthCallback(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -443,7 +427,7 @@ func TestGitAuthCallback(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) diff --git a/coderd/gitsshkey_test.go b/coderd/gitsshkey_test.go index a406ed6a1d5d2..be1f43c52eb2f 100644 --- a/coderd/gitsshkey_test.go +++ b/coderd/gitsshkey_test.go @@ -108,7 +108,7 @@ func TestAgentGitSSHKey(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) project := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) diff --git a/coderd/insights_test.go b/coderd/insights_test.go index bb28f113bd332..23f14ad8b5255 100644 --- a/coderd/insights_test.go +++ b/coderd/insights_test.go @@ -40,7 +40,7 @@ func TestDeploymentInsights(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -126,7 +126,7 @@ func TestUserLatencyInsights(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -278,10 +278,10 @@ func TestTemplateInsights(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{ + ProvisionPlan: []*proto.Response{ { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ Parameters: []*proto.RichParameter{ {Name: firstParameterName, DisplayName: firstParameterDisplayName, Type: firstParameterType, Description: firstParameterDescription, Required: true}, {Name: secondParameterName, DisplayName: secondParameterDisplayName, Type: secondParameterType, Description: secondParameterDescription, Required: true}, @@ -295,9 +295,9 @@ func TestTemplateInsights(t *testing.T) { }, }, }, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", diff --git a/coderd/prometheusmetrics/prometheusmetrics_test.go b/coderd/prometheusmetrics/prometheusmetrics_test.go index c6d65418cb4b6..bf6f475ad1be6 100644 --- a/coderd/prometheusmetrics/prometheusmetrics_test.go +++ b/coderd/prometheusmetrics/prometheusmetrics_test.go @@ -268,10 +268,10 @@ func TestAgents(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -494,7 +494,7 @@ func prepareWorkspaceAndAgent(t *testing.T, client *codersdk.Client, user coders version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go index efb942f8a32ae..f61606a1425b9 100644 --- a/coderd/provisionerdserver/provisionerdserver.go +++ b/coderd/provisionerdserver/provisionerdserver.go @@ -280,7 +280,7 @@ func (server *Server) AcquireJob(ctx context.Context, _ *proto.Empty) (*proto.Ac RichParameterValues: convertRichParameterValues(workspaceBuildParameters), VariableValues: asVariableValues(templateVariables), GitAuthProviders: gitAuthProviders, - Metadata: &sdkproto.Provision_Metadata{ + Metadata: &sdkproto.Metadata{ CoderUrl: server.AccessURL.String(), WorkspaceTransition: transition, WorkspaceName: workspace.Name, @@ -316,7 +316,7 @@ func (server *Server) AcquireJob(ctx context.Context, _ *proto.Empty) (*proto.Ac TemplateDryRun: &proto.AcquiredJob_TemplateDryRun{ RichParameterValues: convertRichParameterValues(input.RichParameterValues), VariableValues: asVariableValues(templateVariables), - Metadata: &sdkproto.Provision_Metadata{ + Metadata: &sdkproto.Metadata{ CoderUrl: server.AccessURL.String(), WorkspaceName: input.WorkspaceName, }, @@ -337,7 +337,7 @@ func (server *Server) AcquireJob(ctx context.Context, _ *proto.Empty) (*proto.Ac protoJob.Type = &proto.AcquiredJob_TemplateImport_{ TemplateImport: &proto.AcquiredJob_TemplateImport{ UserVariableValues: convertVariableValues(userVariableValues), - Metadata: &sdkproto.Provision_Metadata{ + Metadata: &sdkproto.Metadata{ CoderUrl: server.AccessURL.String(), }, }, diff --git a/coderd/provisionerdserver/provisionerdserver_test.go b/coderd/provisionerdserver/provisionerdserver_test.go index f53933722458c..5a317cd531530 100644 --- a/coderd/provisionerdserver/provisionerdserver_test.go +++ b/coderd/provisionerdserver/provisionerdserver_test.go @@ -267,7 +267,7 @@ func TestAcquireJob(t *testing.T) { Id: gitAuthProvider, AccessToken: "access_token", }}, - Metadata: &sdkproto.Provision_Metadata{ + Metadata: &sdkproto.Metadata{ CoderUrl: srv.AccessURL.String(), WorkspaceTransition: sdkproto.WorkspaceTransition_START, WorkspaceName: workspace.Name, @@ -359,7 +359,7 @@ func TestAcquireJob(t *testing.T) { want, err := json.Marshal(&proto.AcquiredJob_TemplateDryRun_{ TemplateDryRun: &proto.AcquiredJob_TemplateDryRun{ - Metadata: &sdkproto.Provision_Metadata{ + Metadata: &sdkproto.Metadata{ CoderUrl: srv.AccessURL.String(), WorkspaceName: "testing", }, @@ -391,7 +391,7 @@ func TestAcquireJob(t *testing.T) { want, err := json.Marshal(&proto.AcquiredJob_TemplateImport_{ TemplateImport: &proto.AcquiredJob_TemplateImport{ - Metadata: &sdkproto.Provision_Metadata{ + Metadata: &sdkproto.Metadata{ CoderUrl: srv.AccessURL.String(), }, }, @@ -434,7 +434,7 @@ func TestAcquireJob(t *testing.T) { UserVariableValues: []*sdkproto.VariableValue{ {Name: "first", Sensitive: true, Value: "first_value"}, }, - Metadata: &sdkproto.Provision_Metadata{ + Metadata: &sdkproto.Metadata{ CoderUrl: srv.AccessURL.String(), }, }, diff --git a/coderd/provisionerjobs_test.go b/coderd/provisionerjobs_test.go index 0bfd00e46a143..5d1715a9fe52d 100644 --- a/coderd/provisionerjobs_test.go +++ b/coderd/provisionerjobs_test.go @@ -20,16 +20,16 @@ func TestProvisionerJobLogs(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Log{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Log{ Log: &proto.Log{ Level: proto.LogLevel_INFO, Output: "log-output", }, }, }, { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{}, }, }}, }) @@ -59,16 +59,16 @@ func TestProvisionerJobLogs(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Log{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Log{ Log: &proto.Log{ Level: proto.LogLevel_INFO, Output: "log-output", }, }, }, { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{}, }, }}, }) diff --git a/coderd/templates_test.go b/coderd/templates_test.go index 92a67710902dd..195accb713947 100644 --- a/coderd/templates_test.go +++ b/coderd/templates_test.go @@ -1203,7 +1203,7 @@ func TestTemplateMetrics(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) diff --git a/coderd/templateversions_test.go b/coderd/templateversions_test.go index f81b29ee82d4c..d06e68fabb368 100644 --- a/coderd/templateversions_test.go +++ b/coderd/templateversions_test.go @@ -136,8 +136,8 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) data, err := echo.Tar(&echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: echo.ProvisionComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionApply: echo.ApplyComplete, + ProvisionPlan: echo.PlanComplete, }) require.NoError(t, err) @@ -245,8 +245,8 @@ func TestPatchCancelTemplateVersion(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Log{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Log{ Log: &proto.Log{}, }, }}, @@ -284,8 +284,8 @@ func TestPatchCancelTemplateVersion(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Log{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Log{ Log: &proto.Log{}, }, }}, @@ -346,9 +346,9 @@ func TestTemplateVersionsGitAuth(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: []*proto.Response{{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ GitAuthProviders: []string{"github"}, }, }, @@ -400,9 +400,9 @@ func TestTemplateVersionResources(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "some", Type: "example", @@ -439,17 +439,17 @@ func TestTemplateVersionLogs(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Log{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Log{ Log: &proto.Log{ Level: proto.LogLevel_INFO, Output: "example", }, }, }, { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "some", Type: "example", @@ -610,15 +610,15 @@ func TestTemplateVersionDryRun(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{ + ProvisionApply: []*proto.Response{ { - Type: &proto.Provision_Response_Log{ + Type: &proto.Response_Log{ Log: &proto.Log{}, }, }, { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{resource}, }, }, @@ -677,8 +677,8 @@ func TestTemplateVersionDryRun(t *testing.T) { // This import job will never finish version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Log{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Log{ Log: &proto.Log{}, }, }}, @@ -705,15 +705,15 @@ func TestTemplateVersionDryRun(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{ + ProvisionApply: []*proto.Response{ { - Type: &proto.Provision_Response_Log{ + Type: &proto.Response_Log{ Log: &proto.Log{}, }, }, { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{}, }, }, }, @@ -776,15 +776,15 @@ func TestTemplateVersionDryRun(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{ + ProvisionApply: []*proto.Response{ { - Type: &proto.Provision_Response_Log{ + Type: &proto.Response_Log{ Log: &proto.Log{}, }, }, { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{}, }, }, }, @@ -1040,21 +1040,17 @@ func TestTemplateVersionVariables(t *testing.T) { createEchoResponses := func(templateVariables []*proto.TemplateVariable) *echo.Responses { return &echo.Responses{ - Parse: []*proto.Parse_Response{ + Parse: []*proto.Response{ { - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{ + Type: &proto.Response_Parse{ + Parse: &proto.ParseComplete{ TemplateVariables: templateVariables, }, }, }, }, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, - }, - }}, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ApplyComplete, } } @@ -1418,10 +1414,10 @@ func TestTemplateVersionParameters_Order(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{ + ProvisionPlan: []*proto.Response{ { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ Parameters: []*proto.RichParameter{ { Name: firstParameterName, @@ -1453,11 +1449,7 @@ func TestTemplateVersionParameters_Order(t *testing.T) { }, }, }, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, - }, - }}, + ProvisionApply: echo.ApplyComplete, }) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) diff --git a/coderd/workspaceagents_test.go b/coderd/workspaceagents_test.go index d1b379d3d74e7..bfe5481471f67 100644 --- a/coderd/workspaceagents_test.go +++ b/coderd/workspaceagents_test.go @@ -43,10 +43,10 @@ func TestWorkspaceAgent(t *testing.T) { tmpDir := t.TempDir() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -87,10 +87,10 @@ func TestWorkspaceAgent(t *testing.T) { tmpDir := t.TempDir() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -132,10 +132,10 @@ func TestWorkspaceAgent(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -188,10 +188,10 @@ func TestWorkspaceAgentStartupLogs(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -252,10 +252,10 @@ func TestWorkspaceAgentStartupLogs(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -319,7 +319,7 @@ func TestWorkspaceAgentListen(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -360,7 +360,7 @@ func TestWorkspaceAgentListen(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) @@ -371,10 +371,10 @@ func TestWorkspaceAgentListen(t *testing.T) { version = coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -419,7 +419,7 @@ func TestWorkspaceAgentTailnet(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -471,7 +471,7 @@ func TestWorkspaceAgentTailnetDirectDisabled(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -548,10 +548,10 @@ func TestWorkspaceAgentListeningPorts(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -806,9 +806,9 @@ func TestWorkspaceAgentAppHealth(t *testing.T) { } version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -893,7 +893,7 @@ func TestWorkspaceAgentReportStats(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -942,7 +942,7 @@ func TestWorkspaceAgent_LifecycleState(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -1014,10 +1014,10 @@ func TestWorkspaceAgent_Metadata(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -1184,7 +1184,7 @@ func TestWorkspaceAgent_Startup(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -1238,7 +1238,7 @@ func TestWorkspaceAgent_Startup(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -1293,7 +1293,7 @@ func TestWorkspaceAgent_UpdatedDERP(t *testing.T) { agentToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(agentToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) diff --git a/coderd/workspaceapps/apptest/setup.go b/coderd/workspaceapps/apptest/setup.go index 9d9a80490146f..6ab541f078072 100644 --- a/coderd/workspaceapps/apptest/setup.go +++ b/coderd/workspaceapps/apptest/setup.go @@ -288,10 +288,10 @@ func createWorkspaceWithApps(t *testing.T, client *codersdk.Client, orgID uuid.U appURL := fmt.Sprintf("%s://127.0.0.1:%d?%s", scheme, port, proxyTestAppQuery) version := coderdtest.CreateTemplateVersion(t, client, orgID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", diff --git a/coderd/workspaceapps/db_test.go b/coderd/workspaceapps/db_test.go index 1783fcec17cda..163247f6d4e4f 100644 --- a/coderd/workspaceapps/db_test.go +++ b/coderd/workspaceapps/db_test.go @@ -94,10 +94,10 @@ func Test_ResolveRequest(t *testing.T) { agentAuthToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, firstUser.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", diff --git a/coderd/workspacebuilds_test.go b/coderd/workspacebuilds_test.go index cd62f6a75046c..0ee810e3e3eda 100644 --- a/coderd/workspacebuilds_test.go +++ b/coderd/workspacebuilds_test.go @@ -376,12 +376,12 @@ func TestPatchCancelWorkspaceBuild(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Log{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Log{ Log: &proto.Log{}, }, }}, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, }) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -401,11 +401,12 @@ func TestPatchCancelWorkspaceBuild(t *testing.T) { require.Eventually(t, func() bool { var err error build, err = client.WorkspaceBuild(ctx, build.ID) + // job gets marked Failed when there is an Error; in practice we never get to Status = Canceled + // because provisioners report an Error when canceled. We check the Error string to ensure we don't mask + // other errors in this test. return assert.NoError(t, err) && - // The job will never actually cancel successfully because it will never send a - // provision complete response. - assert.Empty(t, build.Job.Error) && - build.Job.Status == codersdk.ProvisionerJobCanceling + build.Job.Error == "canceled" && + build.Job.Status == codersdk.ProvisionerJobFailed }, testutil.WaitShort, testutil.IntervalFast) }) t.Run("User is not allowed to cancel", func(t *testing.T) { @@ -415,12 +416,12 @@ func TestPatchCancelWorkspaceBuild(t *testing.T) { owner := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Log{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Log{ Log: &proto.Log{}, }, }}, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, }) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID) @@ -452,9 +453,9 @@ func TestWorkspaceBuildResources(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "some", Type: "example", @@ -494,16 +495,16 @@ func TestWorkspaceBuildLogs(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Log{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Log{ Log: &proto.Log{ Level: proto.LogLevel_INFO, Output: "example", }, }, }, { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "some", Type: "example", @@ -548,10 +549,10 @@ func TestWorkspaceBuildState(t *testing.T) { wantState := []byte("some kinda state") version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ State: wantState, }, }, @@ -764,31 +765,31 @@ func TestWorkspaceBuildDebugMode(t *testing.T) { // Interact as template admin echoResponses := &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Log{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Log{ Log: &proto.Log{ Level: proto.LogLevel_DEBUG, Output: "want-it", }, }, }, { - Type: &proto.Provision_Response_Log{ + Type: &proto.Response_Log{ Log: &proto.Log{ Level: proto.LogLevel_TRACE, Output: "dont-want-it", }, }, }, { - Type: &proto.Provision_Response_Log{ + Type: &proto.Response_Log{ Log: &proto.Log{ Level: proto.LogLevel_DEBUG, Output: "done", }, }, }, { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{}, }, }}, } @@ -831,7 +832,10 @@ func TestWorkspaceBuildDebugMode(t *testing.T) { if !ok { break processingLogs } - + t.Logf("got log: %s -- %s | %s | %s", log.Level, log.Stage, log.Source, log.Output) + if log.Source != "provisioner" { + continue + } logsProcessed++ require.NotEqual(t, "dont-want-it", log.Output, "unexpected log message", "%s log message shouldn't be logged: %s") @@ -841,7 +845,6 @@ func TestWorkspaceBuildDebugMode(t *testing.T) { } } } - - require.Len(t, echoResponses.ProvisionApply, logsProcessed) + require.Equal(t, 2, logsProcessed) }) } diff --git a/coderd/workspaceresourceauth_test.go b/coderd/workspaceresourceauth_test.go index feadc62ddecb9..fdf1bd2335034 100644 --- a/coderd/workspaceresourceauth_test.go +++ b/coderd/workspaceresourceauth_test.go @@ -26,9 +26,9 @@ func TestPostWorkspaceAuthAzureInstanceIdentity(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "somename", Type: "someinstance", @@ -71,9 +71,9 @@ func TestPostWorkspaceAuthAWSInstanceIdentity(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "somename", Type: "someinstance", @@ -157,9 +157,9 @@ func TestPostWorkspaceAuthGoogleInstanceIdentity(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "somename", Type: "someinstance", diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index b42f4517db82d..63442e9f83795 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -174,9 +174,9 @@ func TestWorkspace(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "some", Type: "example", @@ -214,9 +214,9 @@ func TestWorkspace(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "some", Type: "example", @@ -258,9 +258,9 @@ func TestWorkspace(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "some", Type: "example", @@ -1248,7 +1248,7 @@ func TestWorkspaceFilterManual(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -1276,7 +1276,7 @@ func TestWorkspaceFilterManual(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -1316,10 +1316,10 @@ func TestWorkspaceFilterManual(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -1374,7 +1374,7 @@ func TestWorkspaceFilterManual(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -1418,7 +1418,7 @@ func TestWorkspaceFilterManual(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -1457,7 +1457,7 @@ func TestWorkspaceFilterManual(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -1575,7 +1575,7 @@ func TestPostWorkspaceBuild(t *testing.T) { client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - ProvisionApply: []*proto.Provision_Response{{}}, + ProvisionApply: []*proto.Response{{}}, }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) @@ -2138,10 +2138,10 @@ func TestWorkspaceWatcher(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -2231,10 +2231,10 @@ func TestWorkspaceWatcher(t *testing.T) { // Add a new version that will fail. badVersion := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Error: "test error", }, }, @@ -2299,9 +2299,9 @@ func TestWorkspaceResource(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "beta", Type: "example", @@ -2367,9 +2367,9 @@ func TestWorkspaceResource(t *testing.T) { } version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "some", Type: "example", @@ -2424,9 +2424,9 @@ func TestWorkspaceResource(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "some", Type: "example", @@ -2497,10 +2497,10 @@ func TestWorkspaceWithRichParameters(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{ + ProvisionPlan: []*proto.Response{ { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ Parameters: []*proto.RichParameter{ { Name: firstParameterName, @@ -2521,9 +2521,9 @@ func TestWorkspaceWithRichParameters(t *testing.T) { }, }, }, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{}, }, }}, }) @@ -2590,10 +2590,10 @@ func TestWorkspaceWithOptionalRichParameters(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{ + ProvisionPlan: []*proto.Response{ { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ Parameters: []*proto.RichParameter{ { Name: firstParameterName, @@ -2612,9 +2612,9 @@ func TestWorkspaceWithOptionalRichParameters(t *testing.T) { }, }, }, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{}, }, }}, }) @@ -2681,10 +2681,10 @@ func TestWorkspaceWithEphemeralRichParameters(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{ + ProvisionPlan: []*proto.Response{ { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ Parameters: []*proto.RichParameter{ { Name: firstParameterName, @@ -2706,9 +2706,9 @@ func TestWorkspaceWithEphemeralRichParameters(t *testing.T) { }, }, }, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{}, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{}, }, }}, }) diff --git a/enterprise/coderd/appearance_test.go b/enterprise/coderd/appearance_test.go index 2cf7259044e83..8ee2c071377d0 100644 --- a/enterprise/coderd/appearance_test.go +++ b/enterprise/coderd/appearance_test.go @@ -111,7 +111,7 @@ func TestServiceBanners(t *testing.T) { agentClient.SetSessionToken(authToken) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, ProvisionApply: echo.ProvisionApplyWithAgent(authToken), }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) diff --git a/enterprise/coderd/provisionerdaemons_test.go b/enterprise/coderd/provisionerdaemons_test.go index d9b688fab8158..e190a3df90e20 100644 --- a/enterprise/coderd/provisionerdaemons_test.go +++ b/enterprise/coderd/provisionerdaemons_test.go @@ -139,9 +139,9 @@ func TestProvisionerDaemonServe(t *testing.T) { authToken := uuid.NewString() data, err := echo.Tar(&echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: []*proto.Response{{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", diff --git a/enterprise/coderd/workspaceagents_test.go b/enterprise/coderd/workspaceagents_test.go index 52e59858f5354..5b7ecbe1bcfd8 100644 --- a/enterprise/coderd/workspaceagents_test.go +++ b/enterprise/coderd/workspaceagents_test.go @@ -73,9 +73,9 @@ func setupWorkspaceAgent(t *testing.T, client *codersdk.Client, user codersdk.Cr authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", diff --git a/enterprise/coderd/workspacequota_test.go b/enterprise/coderd/workspacequota_test.go index 3119168696a36..69c9a4bc3de88 100644 --- a/enterprise/coderd/workspacequota_test.go +++ b/enterprise/coderd/workspacequota_test.go @@ -89,9 +89,9 @@ func TestWorkspaceQuota(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -183,39 +183,15 @@ func TestWorkspaceQuota(t *testing.T) { require.NoError(t, err) verifyQuota(ctx, t, client, 0, 4) - stopResp := []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Resources: []*proto.Resource{{ - Name: "example", - Type: "aws_instance", - DailyCost: 1, - }}, - }, - }, - }} - - startResp := []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Resources: []*proto.Resource{{ - Name: "example", - Type: "aws_instance", - DailyCost: 2, - }}, - }, - }, - }} - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlanMap: map[proto.WorkspaceTransition][]*proto.Provision_Response{ - proto.WorkspaceTransition_START: startResp, - proto.WorkspaceTransition_STOP: stopResp, + ProvisionPlanMap: map[proto.WorkspaceTransition][]*proto.Response{ + proto.WorkspaceTransition_START: planWithCost(2), + proto.WorkspaceTransition_STOP: planWithCost(1), }, - ProvisionApplyMap: map[proto.WorkspaceTransition][]*proto.Provision_Response{ - proto.WorkspaceTransition_START: startResp, - proto.WorkspaceTransition_STOP: stopResp, + ProvisionApplyMap: map[proto.WorkspaceTransition][]*proto.Response{ + proto.WorkspaceTransition_START: applyWithCost(2), + proto.WorkspaceTransition_STOP: applyWithCost(1), }, }) @@ -258,3 +234,31 @@ func TestWorkspaceQuota(t *testing.T) { require.Equal(t, codersdk.WorkspaceStatusRunning, build.Status) }) } + +func planWithCost(cost int32) []*proto.Response { + return []*proto.Response{{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ + Resources: []*proto.Resource{{ + Name: "example", + Type: "aws_instance", + DailyCost: cost, + }}, + }, + }, + }} +} + +func applyWithCost(cost int32) []*proto.Response { + return []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ + Resources: []*proto.Resource{{ + Name: "example", + Type: "aws_instance", + DailyCost: cost, + }}, + }, + }, + }} +} diff --git a/enterprise/coderd/workspaces_test.go b/enterprise/coderd/workspaces_test.go index c5a8aec6b8535..0f94d20ff11cc 100644 --- a/enterprise/coderd/workspaces_test.go +++ b/enterprise/coderd/workspaces_test.go @@ -120,8 +120,8 @@ func TestWorkspaceAutobuild(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: echo.ProvisionFailed, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ApplyFailed, }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { ctr.FailureTTLMillis = ptr.Ref[int64](failureTTL.Milliseconds()) @@ -166,8 +166,8 @@ func TestWorkspaceAutobuild(t *testing.T) { }) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: echo.ProvisionFailed, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ApplyFailed, }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { ctr.FailureTTLMillis = ptr.Ref[int64](failureTTL.Milliseconds()) @@ -212,8 +212,8 @@ func TestWorkspaceAutobuild(t *testing.T) { }) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ApplyComplete, }) // Create a template without setting a failure_ttl. template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -255,8 +255,8 @@ func TestWorkspaceAutobuild(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ApplyComplete, }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { ctr.InactivityTTLMillis = ptr.Ref[int64](inactiveTTL.Milliseconds()) @@ -311,8 +311,8 @@ func TestWorkspaceAutobuild(t *testing.T) { }) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ApplyComplete, }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { ctr.InactivityTTLMillis = ptr.Ref[int64](inactiveTTL.Milliseconds()) @@ -353,8 +353,8 @@ func TestWorkspaceAutobuild(t *testing.T) { }) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ApplyComplete, }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { ctr.LockedTTLMillis = ptr.Ref[int64](lockedTTL.Milliseconds()) @@ -395,8 +395,8 @@ func TestWorkspaceAutobuild(t *testing.T) { }) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ApplyComplete, }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { ctr.InactivityTTLMillis = ptr.Ref[int64](inactiveTTL.Milliseconds()) @@ -447,8 +447,8 @@ func TestWorkspaceAutobuild(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ApplyComplete, }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { ctr.InactivityTTLMillis = ptr.Ref[int64](transitionTTL.Milliseconds()) @@ -516,8 +516,8 @@ func TestWorkspaceAutobuild(t *testing.T) { }) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ApplyComplete, }) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { ctr.LockedTTLMillis = ptr.Ref[int64](lockedTTL.Milliseconds()) @@ -578,8 +578,8 @@ func TestWorkspaceAutobuild(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: echo.ProvisionComplete, + ProvisionPlan: echo.PlanComplete, + ProvisionApply: echo.ApplyComplete, }) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) diff --git a/scaletest/agentconn/run_test.go b/scaletest/agentconn/run_test.go index e9697ddedeb7a..4d3ffb8d0da2d 100644 --- a/scaletest/agentconn/run_test.go +++ b/scaletest/agentconn/run_test.go @@ -231,10 +231,10 @@ func setupRunnerTest(t *testing.T) (client *codersdk.Client, agentID uuid.UUID) authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", diff --git a/scaletest/createworkspaces/run_test.go b/scaletest/createworkspaces/run_test.go index b1d871cefd743..b69297f622676 100644 --- a/scaletest/createworkspaces/run_test.go +++ b/scaletest/createworkspaces/run_test.go @@ -48,10 +48,10 @@ func Test_Runner(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{ { - Type: &proto.Provision_Response_Log{ + Type: &proto.Response_Log{ Log: &proto.Log{ Level: proto.LogLevel_INFO, Output: "hello from logs", @@ -59,8 +59,8 @@ func Test_Runner(t *testing.T) { }, }, { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{ { Name: "example", @@ -170,10 +170,10 @@ func Test_Runner(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{ { - Type: &proto.Provision_Response_Log{Log: &proto.Log{}}, + Type: &proto.Response_Log{Log: &proto.Log{}}, }, }, }) @@ -282,10 +282,10 @@ func Test_Runner(t *testing.T) { authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{ { - Type: &proto.Provision_Response_Log{ + Type: &proto.Response_Log{ Log: &proto.Log{ Level: proto.LogLevel_INFO, Output: "hello from logs", @@ -293,8 +293,8 @@ func Test_Runner(t *testing.T) { }, }, { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{ { Name: "example", @@ -407,11 +407,11 @@ func Test_Runner(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{ { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Error: "test error", }, }, diff --git a/scaletest/reconnectingpty/run_test.go b/scaletest/reconnectingpty/run_test.go index 8b45f9e01587b..81de3dcfb9da8 100644 --- a/scaletest/reconnectingpty/run_test.go +++ b/scaletest/reconnectingpty/run_test.go @@ -252,10 +252,10 @@ func setupRunnerTest(t *testing.T) (client *codersdk.Client, agentID uuid.UUID) authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", diff --git a/scaletest/workspacebuild/run_test.go b/scaletest/workspacebuild/run_test.go index 2b50c95bdad5f..c07b10f8095b9 100644 --- a/scaletest/workspacebuild/run_test.go +++ b/scaletest/workspacebuild/run_test.go @@ -45,10 +45,10 @@ func Test_Runner(t *testing.T) { authToken3 := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{ { - Type: &proto.Provision_Response_Log{ + Type: &proto.Response_Log{ Log: &proto.Log{ Level: proto.LogLevel_INFO, Output: "hello from logs", @@ -56,8 +56,8 @@ func Test_Runner(t *testing.T) { }, }, { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{ { Name: "example1", @@ -199,11 +199,11 @@ func Test_Runner(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{ { - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Error: "test error", }, }, diff --git a/scaletest/workspacetraffic/run_test.go b/scaletest/workspacetraffic/run_test.go index 4077a266aa124..308630910427d 100644 --- a/scaletest/workspacetraffic/run_test.go +++ b/scaletest/workspacetraffic/run_test.go @@ -41,10 +41,10 @@ func TestRun(t *testing.T) { agentName = "agent" version = coderdtest.CreateTemplateVersion(t, client, firstUser.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", @@ -154,10 +154,10 @@ func TestRun(t *testing.T) { agentName = "agent" version = coderdtest.CreateTemplateVersion(t, client, firstUser.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - ProvisionPlan: echo.ProvisionComplete, - ProvisionApply: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ + ProvisionPlan: echo.PlanComplete, + ProvisionApply: []*proto.Response{{ + Type: &proto.Response_Apply{ + Apply: &proto.ApplyComplete{ Resources: []*proto.Resource{{ Name: "example", Type: "aws_instance", From 39d606537bdba85758ac124001584ae60e984d86 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Wed, 23 Aug 2023 09:51:48 +0000 Subject: [PATCH 05/13] Fixes from self-review Signed-off-by: Spike Curtis --- provisioner/echo/serve.go | 1 - provisionersdk/session.go | 8 +++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/provisioner/echo/serve.go b/provisioner/echo/serve.go index 5f4b6f2e95edf..27d3d7e6ab44d 100644 --- a/provisioner/echo/serve.go +++ b/provisioner/echo/serve.go @@ -188,7 +188,6 @@ func (e *echo) Apply(sess *provisionersdk.Session, req *proto.ApplyRequest, canc // some tests use Echo without a complete response to test cancel <-canceledOrComplete - // we have to return a clean Complete or the status will go to "failed" return provisionersdk.ApplyErrorf("canceled") } diff --git a/provisionersdk/session.go b/provisionersdk/session.go index fa5e63e7b5ea6..cb9bd3a699b85 100644 --- a/provisionersdk/session.go +++ b/provisionersdk/session.go @@ -177,8 +177,6 @@ func (s *Session) Context() context.Context { func (s *Session) ExtractArchive() error { ctx := s.Context() - //s.ProvisionLog(proto.LogLevel_INFO, "Setting up") - s.Logger.Info(ctx, "unpacking template source archive", slog.F("size_bytes", len(s.Config.TemplateSourceArchive)), ) @@ -194,7 +192,11 @@ func (s *Session) ExtractArchive() error { } return xerrors.Errorf("read template source archive: %w", err) } - // #nosec + // Security: don't untar absolute or relative paths, as this can allow a malicious tar to overwrite + // files outside the workdir. + if !filepath.IsLocal(header.Name) { + return xerrors.Errorf("refusing to extract to non-local path") + } headerPath := filepath.Join(s.WorkDirectory, header.Name) if !strings.HasPrefix(headerPath, filepath.Clean(s.WorkDirectory)) { return xerrors.New("tar attempts to target relative upper directory") From e39b8a21e866fb2a678503b86389ee81c3fd9830 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Wed, 23 Aug 2023 11:12:51 +0000 Subject: [PATCH 06/13] appease fmt & link Signed-off-by: Spike Curtis --- provisioner/echo/serve.go | 7 +++---- provisioner/echo/serve_test.go | 4 +++- provisioner/terraform/provision.go | 3 ++- provisioner/terraform/provision_test.go | 7 ++----- provisionerd/runner/runner.go | 7 +++---- provisionersdk/serve_test.go | 6 +++--- provisionersdk/session.go | 13 +++++++++---- 7 files changed, 25 insertions(+), 22 deletions(-) diff --git a/provisioner/echo/serve.go b/provisioner/echo/serve.go index 27d3d7e6ab44d..9e22157bc381b 100644 --- a/provisioner/echo/serve.go +++ b/provisioner/echo/serve.go @@ -123,11 +123,10 @@ func readResponses(sess *provisionersdk.Session, trans string, suffix string) ([ break } } - return responses, nil } // Parse reads requests from the provided directory to stream responses. -func (e *echo) Parse(sess *provisionersdk.Session, _ *proto.ParseRequest, _ <-chan struct{}) *proto.ParseComplete { +func (*echo) Parse(sess *provisionersdk.Session, _ *proto.ParseRequest, _ <-chan struct{}) *proto.ParseComplete { responses, err := readResponses(sess, "unspecified", "parse.protobuf") if err != nil { return &proto.ParseComplete{Error: err.Error()} @@ -146,7 +145,7 @@ func (e *echo) Parse(sess *provisionersdk.Session, _ *proto.ParseRequest, _ <-ch } // Plan reads requests from the provided directory to stream responses. -func (e *echo) Plan(sess *provisionersdk.Session, req *proto.PlanRequest, canceledOrComplete <-chan struct{}) *proto.PlanComplete { +func (*echo) Plan(sess *provisionersdk.Session, req *proto.PlanRequest, canceledOrComplete <-chan struct{}) *proto.PlanComplete { responses, err := readResponses( sess, strings.ToLower(req.GetMetadata().GetWorkspaceTransition().String()), @@ -169,7 +168,7 @@ func (e *echo) Plan(sess *provisionersdk.Session, req *proto.PlanRequest, cancel } // Apply reads requests from the provided directory to stream responses. -func (e *echo) Apply(sess *provisionersdk.Session, req *proto.ApplyRequest, canceledOrComplete <-chan struct{}) *proto.ApplyComplete { +func (*echo) Apply(sess *provisionersdk.Session, req *proto.ApplyRequest, canceledOrComplete <-chan struct{}) *proto.ApplyComplete { responses, err := readResponses( sess, strings.ToLower(req.GetMetadata().GetWorkspaceTransition().String()), diff --git a/provisioner/echo/serve_test.go b/provisioner/echo/serve_test.go index 622f785da7074..6590f2ecafc54 100644 --- a/provisioner/echo/serve_test.go +++ b/provisioner/echo/serve_test.go @@ -52,7 +52,8 @@ func TestEcho(t *testing.T) { Type: &proto.Response_Parse{ Parse: &proto.ParseComplete{}, }, - }} + }, + } data, err := echo.Tar(&echo.Responses{ Parse: responses, }) @@ -69,6 +70,7 @@ func TestEcho(t *testing.T) { require.NoError(t, err) err = client.Send(&proto.Request{Type: &proto.Request_Parse{Parse: &proto.ParseRequest{}}}) + require.NoError(t, err) log, err := client.Recv() require.NoError(t, err) require.Equal(t, responses[0].GetLog().Output, log.GetLog().Output) diff --git a/provisioner/terraform/provision.go b/provisioner/terraform/provision.go index f7d2d6f2326b2..ab832e4408683 100644 --- a/provisioner/terraform/provision.go +++ b/provisioner/terraform/provision.go @@ -1,13 +1,14 @@ package terraform import ( - "cdr.dev/slog" "context" "fmt" "os" "strings" "time" + "cdr.dev/slog" + "github.com/coder/coder/v2/coderd/tracing" "github.com/coder/coder/v2/provisionersdk" "github.com/coder/coder/v2/provisionersdk/proto" diff --git a/provisioner/terraform/provision_test.go b/provisioner/terraform/provision_test.go index 9fa56309a6f5a..254ddec45b5e6 100644 --- a/provisioner/terraform/provision_test.go +++ b/provisioner/terraform/provision_test.go @@ -96,9 +96,7 @@ func configure(ctx context.Context, t *testing.T, client proto.DRPCProvisionerCl } func readProvisionLog(t *testing.T, response proto.DRPCProvisioner_SessionClient) string { - var ( - logBuf strings.Builder - ) + var logBuf strings.Builder for { msg, err := response.Recv() require.NoError(t, err) @@ -647,7 +645,6 @@ func TestProvision(t *testing.T) { require.NoError(t, err) require.Equal(t, string(resourcesWant), string(resourcesGot)) } - } if !gotExpectedLog { @@ -740,7 +737,7 @@ func TestProvision_SafeEnv(t *testing.T) { _ = readProvisionLog(t, sess) - err = sess.Send(&proto.Request{Type: &proto.Request_Apply{Apply: &proto.ApplyRequest{}}}) + err = sendApply(sess, proto.WorkspaceTransition_START) require.NoError(t, err) log := readProvisionLog(t, sess) diff --git a/provisionerd/runner/runner.go b/provisionerd/runner/runner.go index d1843b43fb0ba..7afa7a0999627 100644 --- a/provisionerd/runner/runner.go +++ b/provisionerd/runner/runner.go @@ -440,8 +440,7 @@ func (r *Runner) do(ctx context.Context) (*proto.CompletedJob, *proto.FailedJob) } func (r *Runner) configure(config *sdkproto.Config) *proto.FailedJob { - var err error - err = r.session.Send(&sdkproto.Request{Type: &sdkproto.Request_Config{Config: config}}) + err := r.session.Send(&sdkproto.Request{Type: &sdkproto.Request_Config{Config: config}}) if err != nil { return r.failedJobf("send config: %s", err) } @@ -941,7 +940,7 @@ func (r *Runner) runWorkspaceBuild(ctx context.Context) (*proto.CompletedJob, *p return nil, r.failedWorkspaceBuildf("invalid message type %T received from provisioner", resp.Type) } if planComplete.Error != "" { - r.logger.Warn(context.Background(), "plan failed", + r.logger.Warn(context.Background(), "plan request failed", slog.F("error", planComplete.Error), ) @@ -954,7 +953,7 @@ func (r *Runner) runWorkspaceBuild(ctx context.Context) (*proto.CompletedJob, *p } } - r.logger.Info(context.Background(), "plan successful", + r.logger.Info(context.Background(), "plan request successful", slog.F("resource_count", len(planComplete.Resources)), slog.F("resources", planComplete.Resources), ) diff --git a/provisionersdk/serve_test.go b/provisionersdk/serve_test.go index 00cbbf19c8890..5548b8495bbb1 100644 --- a/provisionersdk/serve_test.go +++ b/provisionersdk/serve_test.go @@ -78,14 +78,14 @@ func TestProvisionerSDK(t *testing.T) { type unimplementedServer struct{} -func (_ unimplementedServer) Parse(_ *provisionersdk.Session, _ *proto.ParseRequest, _ <-chan struct{}) *proto.ParseComplete { +func (unimplementedServer) Parse(_ *provisionersdk.Session, _ *proto.ParseRequest, _ <-chan struct{}) *proto.ParseComplete { return &proto.ParseComplete{Error: "unimplemented"} } -func (_ unimplementedServer) Plan(_ *provisionersdk.Session, _ *proto.PlanRequest, _ <-chan struct{}) *proto.PlanComplete { +func (unimplementedServer) Plan(_ *provisionersdk.Session, _ *proto.PlanRequest, _ <-chan struct{}) *proto.PlanComplete { return &proto.PlanComplete{} } -func (_ unimplementedServer) Apply(_ *provisionersdk.Session, _ *proto.ApplyRequest, _ <-chan struct{}) *proto.ApplyComplete { +func (unimplementedServer) Apply(_ *provisionersdk.Session, _ *proto.ApplyRequest, _ <-chan struct{}) *proto.ApplyComplete { return &proto.ApplyComplete{Error: "unimplemented"} } diff --git a/provisionersdk/session.go b/provisionersdk/session.go index cb9bd3a699b85..3230f12a66e68 100644 --- a/provisionersdk/session.go +++ b/provisionersdk/session.go @@ -3,16 +3,18 @@ package provisionersdk import ( "archive/tar" "bytes" - "cdr.dev/slog" "context" "fmt" - "golang.org/x/xerrors" "io" "os" "path/filepath" "strings" "time" + "cdr.dev/slog" + + "golang.org/x/xerrors" + "github.com/coder/coder/v2/provisionersdk/proto" ) @@ -197,6 +199,7 @@ func (s *Session) ExtractArchive() error { if !filepath.IsLocal(header.Name) { return xerrors.Errorf("refusing to extract to non-local path") } + // nolint: gosec headerPath := filepath.Join(s.WorkDirectory, header.Name) if !strings.HasPrefix(headerPath, filepath.Clean(s.WorkDirectory)) { return xerrors.New("tar attempts to target relative upper directory") @@ -291,8 +294,10 @@ func (r *request[R, C]) do() (C, error) { if req.GetCancel() != nil { return c, nil } - return c, xerrors.Errorf("got new request or nil while old request still processing", - slog.F("request", req)) + if req == nil { + return c, xerrors.New("got nil while old request still processing") + } + return c, xerrors.Errorf("got new request %T while old request still processing", req.Type) case c := <-result: close(canceledOrComplete) return c, nil From d92608eaf8abf386ba79e05ac01966b0f7ddd73d Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Wed, 23 Aug 2023 12:57:05 +0000 Subject: [PATCH 07/13] code review fixes & e2e fixes Signed-off-by: Spike Curtis --- cli/server.go | 1 + coderd/coderdtest/coderdtest.go | 1 + provisionersdk/proto/provisioner.pb.go | 4 +- provisionersdk/proto/provisioner.proto | 2 +- provisionersdk/proto/provisioner_drpc.pb.go | 6 +- provisionersdk/serve_test.go | 4 +- provisionersdk/session.go | 4 +- site/e2e/helpers.ts | 188 +++++++----- site/e2e/provisionerGenerated.ts | 314 ++++++++++---------- site/e2e/tests/app.spec.ts | 2 +- site/e2e/tests/createWorkspace.spec.ts | 2 +- site/e2e/tests/outdatedAgent.spec.ts | 2 +- site/e2e/tests/outdatedCLI.spec.ts | 2 +- site/e2e/tests/webTerminal.spec.ts | 2 +- site/src/api/api.ts | 4 +- 15 files changed, 288 insertions(+), 250 deletions(-) diff --git a/cli/server.go b/cli/server.go index 0ac71095065ee..9d6b4f975cc79 100644 --- a/cli/server.go +++ b/cli/server.go @@ -1306,6 +1306,7 @@ func newProvisionerDaemon( err := echo.Serve(ctx, &provisionersdk.ServeOptions{ Listener: echoServer, WorkDirectory: workDir, + Logger: logger.Named("echo"), }) if err != nil { select { diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go index 4ea2b82413567..4f92665d68e91 100644 --- a/coderd/coderdtest/coderdtest.go +++ b/coderd/coderdtest/coderdtest.go @@ -472,6 +472,7 @@ func NewProvisionerDaemon(t testing.TB, coderAPI *coderd.API) io.Closer { err := echo.Serve(ctx, &provisionersdk.ServeOptions{ Listener: echoServer, WorkDirectory: t.TempDir(), + Logger: coderAPI.Logger.Named("echo").Leveled(slog.LevelDebug), }) assert.NoError(t, err) }() diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go index f7f13b19f5b2e..c0ea0be327953 100644 --- a/provisionersdk/proto/provisioner.pb.go +++ b/provisionersdk/proto/provisioner.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v3.21.12 +// protoc-gen-go v1.30.0 +// protoc v4.23.3 // source: provisionersdk/proto/provisioner.proto package proto diff --git a/provisionersdk/proto/provisioner.proto b/provisionersdk/proto/provisioner.proto index 4d1b2c934c8d1..f44b781bead55 100644 --- a/provisionersdk/proto/provisioner.proto +++ b/provisionersdk/proto/provisioner.proto @@ -272,7 +272,7 @@ service Provisioner { // request an apply. If the daemon closes the Session without an apply, the plan data may be safely discarded. // // The daemon may send a CancelRequest, asynchronously to ask the provisioner to cancel the previous ParseRequest, - // PlanRequest, or ApplyRequest. The provisioner MUST reply with a complete message cooresponding to the request + // PlanRequest, or ApplyRequest. The provisioner MUST reply with a complete message corresponding to the request // that was canceled. If the provisioner has already completed the request, it may ignore the CancelRequest. rpc Session(stream Request) returns (stream Response); } diff --git a/provisionersdk/proto/provisioner_drpc.pb.go b/provisionersdk/proto/provisioner_drpc.pb.go index 06b331bce5f6f..de310e779dcaa 100644 --- a/provisionersdk/proto/provisioner_drpc.pb.go +++ b/provisionersdk/proto/provisioner_drpc.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-drpc. DO NOT EDIT. -// protoc-gen-go-drpc version: (devel) +// protoc-gen-go-drpc version: v0.0.33 // source: provisionersdk/proto/provisioner.proto package proto @@ -70,6 +70,10 @@ type drpcProvisioner_SessionClient struct { drpc.Stream } +func (x *drpcProvisioner_SessionClient) GetStream() drpc.Stream { + return x.Stream +} + func (x *drpcProvisioner_SessionClient) Send(m *Request) error { return x.MsgSend(m, drpcEncoding_File_provisionersdk_proto_provisioner_proto{}) } diff --git a/provisionersdk/serve_test.go b/provisionersdk/serve_test.go index 5548b8495bbb1..baa5d2ba62b28 100644 --- a/provisionersdk/serve_test.go +++ b/provisionersdk/serve_test.go @@ -35,9 +35,7 @@ func TestProvisionerSDK(t *testing.T) { }() api := proto.NewDRPCProvisionerClient(client) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - s, err := api.Session(context.Background()) + s, err := api.Session(ctx) require.NoError(t, err) err = s.Send(&proto.Request{Type: &proto.Request_Config{Config: &proto.Config{}}}) require.NoError(t, err) diff --git a/provisionersdk/session.go b/provisionersdk/session.go index 3230f12a66e68..54418b1b14c7a 100644 --- a/provisionersdk/session.go +++ b/provisionersdk/session.go @@ -214,7 +214,9 @@ func (s *Session) ExtractArchive() error { if err != nil { return xerrors.Errorf("mkdir %q: %w", headerPath, err) } - s.Logger.Debug(context.Background(), "extracted directory", slog.F("path", headerPath)) + s.Logger.Debug(context.Background(), "extracted directory", + slog.F("path", headerPath), + slog.F("mode", fmt.Sprintf("%O", mode))) case tar.TypeReg: file, err := os.OpenFile(headerPath, os.O_CREATE|os.O_RDWR, mode) if err != nil { diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index 6525fa3b01f9f..ea52356d417e9 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -8,10 +8,10 @@ import { Agent, App, AppSharingLevel, - Parse_Complete, - Parse_Response, - Provision_Complete, - Provision_Response, + Response, + ParseComplete, + PlanComplete, + ApplyComplete, Resource, RichParameter, } from "./provisionerGenerated" @@ -337,11 +337,11 @@ type RecursivePartial = { interface EchoProvisionerResponses { // parse is for observing any Terraform variables - parse?: RecursivePartial[] + parse?: RecursivePartial[] // plan occurs when the template is imported - plan?: RecursivePartial[] + plan?: RecursivePartial[] // apply occurs when the workspace is built - apply?: RecursivePartial[] + apply?: RecursivePartial[] } // createTemplateVersionTar consumes a series of echo provisioner protobufs and @@ -353,109 +353,128 @@ const createTemplateVersionTar = async ( responses = {} } if (!responses.parse) { - responses.parse = [{}] + responses.parse = [{ + parse: {} + }] } if (!responses.apply) { - responses.apply = [{}] + responses.apply = [{ + apply: {} + }] } if (!responses.plan) { - responses.plan = responses.apply + responses.plan = responses.apply.map( + response => { + if (response.log) { + return response + } + return { + plan: { + error: response.apply?.error ?? "", + resources: response.apply?.resources ?? [], + parameters: response.apply?.parameters ?? [], + gitAuthProviders: response.apply?.gitAuthProviders ?? [], + } + } + }) } const tar = new TarWriter() responses.parse.forEach((response, index) => { - response.complete = { + response.parse = { templateVariables: [], - ...response.complete, - } as Parse_Complete + error: "", + readme: new Uint8Array(), + ...response.parse, + } as ParseComplete tar.addFile( `${index}.parse.protobuf`, - Parse_Response.encode(response as Parse_Response).finish(), + Response.encode(response as Response).finish(), ) }) - const fillProvisionResponse = ( - response: RecursivePartial, - ) => { - response.complete = { - error: "", - state: new Uint8Array(), - resources: [], - parameters: [], - gitAuthProviders: [], - plan: new Uint8Array(), - ...response.complete, - } as Provision_Complete - response.complete.resources = response.complete.resources?.map( - (resource) => { - if (resource.agents) { - resource.agents = resource.agents?.map((agent) => { - if (agent.apps) { - agent.apps = agent.apps?.map((app) => { - return { - command: "", - displayName: "example", - external: false, - icon: "", - sharingLevel: AppSharingLevel.PUBLIC, - slug: "example", - subdomain: false, - url: "", - ...app, - } as App - }) - } + const fillResource = (resource: RecursivePartial) => { + if (resource.agents) { + resource.agents = resource.agents?.map((agent: RecursivePartial) => { + if (agent.apps) { + agent.apps = agent.apps?.map((app: RecursivePartial) => { return { - apps: [], - architecture: "amd64", - connectionTimeoutSeconds: 300, - directory: "", - env: {}, - id: randomUUID(), - metadata: [], - motdFile: "", - name: "dev", - operatingSystem: "linux", - shutdownScript: "", - shutdownScriptTimeoutSeconds: 0, - startupScript: "", - startupScriptBehavior: "", - startupScriptTimeoutSeconds: 300, - troubleshootingUrl: "", - token: randomUUID(), - ...agent, - } as Agent + command: "", + displayName: "example", + external: false, + icon: "", + sharingLevel: AppSharingLevel.PUBLIC, + slug: "example", + subdomain: false, + url: "", + ...app, + } as App }) } return { - agents: [], - dailyCost: 0, - hide: false, - icon: "", - instanceType: "", + apps: [], + architecture: "amd64", + connectionTimeoutSeconds: 300, + directory: "", + env: {}, + id: randomUUID(), metadata: [], + motdFile: "", name: "dev", - type: "echo", - ...resource, - } as Resource - }, - ) + operatingSystem: "linux", + shutdownScript: "", + shutdownScriptTimeoutSeconds: 0, + startupScript: "", + startupScriptBehavior: "", + startupScriptTimeoutSeconds: 300, + troubleshootingUrl: "", + token: randomUUID(), + ...agent, + } as Agent + }) + } + return { + agents: [], + dailyCost: 0, + hide: false, + icon: "", + instanceType: "", + metadata: [], + name: "dev", + type: "echo", + ...resource, + } as Resource } responses.apply.forEach((response, index) => { - fillProvisionResponse(response) + response.apply = { + error: "", + state: new Uint8Array(), + resources: [], + parameters: [], + gitAuthProviders: [], + ...response.apply, + } as ApplyComplete + response.apply.resources = response.apply.resources?.map(fillResource) tar.addFile( - `${index}.provision.apply.protobuf`, - Provision_Response.encode(response as Provision_Response).finish(), + `${index}.apply.protobuf`, + Response.encode(response as Response).finish(), ) }) responses.plan.forEach((response, index) => { - fillProvisionResponse(response) + response.plan = { + error: "", + resources: [], + parameters: [], + gitAuthProviders: [], + ...response.plan, + } as PlanComplete + response.plan.resources = response.plan.resources?.map(fillResource) tar.addFile( - `${index}.provision.plan.protobuf`, - Provision_Response.encode(response as Provision_Response).finish(), + `${index}.plan.protobuf`, + Response.encode(response as Response).finish(), ) }) const tarFile = await tar.write() @@ -512,16 +531,21 @@ export const echoResponsesWithParameters = ( richParameters: RichParameter[], ): EchoProvisionerResponses => { return { + parse: [ + { + parse: {} + }, + ], plan: [ { - complete: { + plan: { parameters: richParameters, }, }, ], apply: [ { - complete: { + apply: { resources: [ { name: "example", diff --git a/site/e2e/provisionerGenerated.ts b/site/e2e/provisionerGenerated.ts index 66b6c222c9ac7..d79d5b422282c 100644 --- a/site/e2e/provisionerGenerated.ts +++ b/site/e2e/provisionerGenerated.ts @@ -21,6 +21,7 @@ export enum AppSharingLevel { UNRECOGNIZED = -1, } +/** WorkspaceTransition is the desired outcome of a build */ export enum WorkspaceTransition { START = 0, STOP = 1, @@ -177,29 +178,8 @@ export interface Resource_Metadata { isNull: boolean } -/** Parse consumes source-code from a directory to produce inputs. */ -export interface Parse {} - -export interface Parse_Request { - directory: string -} - -export interface Parse_Complete { - templateVariables: TemplateVariable[] -} - -export interface Parse_Response { - log?: Log | undefined - complete?: Parse_Complete | undefined -} - -/** - * Provision consumes source-code from a directory to produce resources. - * Exactly one of Plan or Apply must be provided in a single session. - */ -export interface Provision {} - -export interface Provision_Metadata { +/** Metadata is information about a workspace used in the execution of a build */ +export interface Metadata { coderUrl: string workspaceTransition: WorkspaceTransition workspaceName: string @@ -213,49 +193,74 @@ export interface Provision_Metadata { workspaceOwnerSessionToken: string } -/** - * Config represents execution configuration shared by both Plan and - * Apply commands. - */ -export interface Provision_Config { - directory: string +/** Config represents execution configuration shared by all subsequent requests in the Session */ +export interface Config { + /** template_source_archive is a tar of the template source files */ + templateSourceArchive: Uint8Array + /** state is the provisioner state (if any) */ state: Uint8Array - metadata: Provision_Metadata | undefined provisionerLogLevel: string } -export interface Provision_Plan { - config: Provision_Config | undefined +/** ParseRequest consumes source-code to produce inputs. */ +export interface ParseRequest {} + +/** ParseComplete indicates a request to parse completed. */ +export interface ParseComplete { + error: string + templateVariables: TemplateVariable[] + readme: Uint8Array +} + +/** PlanRequest asks the provisioner to plan what resources & parameters it will create */ +export interface PlanRequest { + metadata: Metadata | undefined richParameterValues: RichParameterValue[] variableValues: VariableValue[] gitAuthProviders: GitAuthProvider[] } -export interface Provision_Apply { - config: Provision_Config | undefined - plan: Uint8Array +/** PlanComplete indicates a request to plan completed. */ +export interface PlanComplete { + error: string + resources: Resource[] + parameters: RichParameter[] + gitAuthProviders: string[] } -export interface Provision_Cancel {} - -export interface Provision_Request { - plan?: Provision_Plan | undefined - apply?: Provision_Apply | undefined - cancel?: Provision_Cancel | undefined +/** + * 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. + */ +export interface ApplyRequest { + metadata: Metadata | undefined } -export interface Provision_Complete { +/** ApplyComplete indicates a request to apply completed. */ +export interface ApplyComplete { state: Uint8Array error: string resources: Resource[] parameters: RichParameter[] gitAuthProviders: string[] - plan: Uint8Array } -export interface Provision_Response { +/** CancelRequest requests that the previous request be canceled gracefully. */ +export interface CancelRequest {} + +export interface Request { + config?: Config | undefined + parse?: ParseRequest | undefined + plan?: PlanRequest | undefined + apply?: ApplyRequest | undefined + cancel?: CancelRequest | undefined +} + +export interface Response { log?: Log | undefined - complete?: Provision_Complete | undefined + parse?: ParseComplete | undefined + plan?: PlanComplete | undefined + apply?: ApplyComplete | undefined } export const Empty = { @@ -648,60 +653,9 @@ export const Resource_Metadata = { }, } -export const Parse = { - encode(_: Parse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - return writer - }, -} - -export const Parse_Request = { +export const Metadata = { encode( - message: Parse_Request, - writer: _m0.Writer = _m0.Writer.create(), - ): _m0.Writer { - if (message.directory !== "") { - writer.uint32(10).string(message.directory) - } - return writer - }, -} - -export const Parse_Complete = { - encode( - message: Parse_Complete, - writer: _m0.Writer = _m0.Writer.create(), - ): _m0.Writer { - for (const v of message.templateVariables) { - TemplateVariable.encode(v!, writer.uint32(10).fork()).ldelim() - } - return writer - }, -} - -export const Parse_Response = { - encode( - message: Parse_Response, - writer: _m0.Writer = _m0.Writer.create(), - ): _m0.Writer { - if (message.log !== undefined) { - Log.encode(message.log, writer.uint32(10).fork()).ldelim() - } - if (message.complete !== undefined) { - Parse_Complete.encode(message.complete, writer.uint32(18).fork()).ldelim() - } - return writer - }, -} - -export const Provision = { - encode(_: Provision, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - return writer - }, -} - -export const Provision_Metadata = { - encode( - message: Provision_Metadata, + message: Metadata, writer: _m0.Writer = _m0.Writer.create(), ): _m0.Writer { if (message.coderUrl !== "") { @@ -741,96 +695,108 @@ export const Provision_Metadata = { }, } -export const Provision_Config = { +export const Config = { encode( - message: Provision_Config, + message: Config, writer: _m0.Writer = _m0.Writer.create(), ): _m0.Writer { - if (message.directory !== "") { - writer.uint32(10).string(message.directory) + if (message.templateSourceArchive.length !== 0) { + writer.uint32(10).bytes(message.templateSourceArchive) } if (message.state.length !== 0) { writer.uint32(18).bytes(message.state) } - if (message.metadata !== undefined) { - Provision_Metadata.encode( - message.metadata, - writer.uint32(26).fork(), - ).ldelim() - } if (message.provisionerLogLevel !== "") { - writer.uint32(34).string(message.provisionerLogLevel) + writer.uint32(26).string(message.provisionerLogLevel) } return writer }, } -export const Provision_Plan = { +export const ParseRequest = { encode( - message: Provision_Plan, + _: ParseRequest, writer: _m0.Writer = _m0.Writer.create(), ): _m0.Writer { - if (message.config !== undefined) { - Provision_Config.encode(message.config, writer.uint32(10).fork()).ldelim() - } - for (const v of message.richParameterValues) { - RichParameterValue.encode(v!, writer.uint32(26).fork()).ldelim() + return writer + }, +} + +export const ParseComplete = { + encode( + message: ParseComplete, + writer: _m0.Writer = _m0.Writer.create(), + ): _m0.Writer { + if (message.error !== "") { + writer.uint32(10).string(message.error) } - for (const v of message.variableValues) { - VariableValue.encode(v!, writer.uint32(34).fork()).ldelim() + for (const v of message.templateVariables) { + TemplateVariable.encode(v!, writer.uint32(18).fork()).ldelim() } - for (const v of message.gitAuthProviders) { - GitAuthProvider.encode(v!, writer.uint32(42).fork()).ldelim() + if (message.readme.length !== 0) { + writer.uint32(26).bytes(message.readme) } return writer }, } -export const Provision_Apply = { +export const PlanRequest = { encode( - message: Provision_Apply, + message: PlanRequest, writer: _m0.Writer = _m0.Writer.create(), ): _m0.Writer { - if (message.config !== undefined) { - Provision_Config.encode(message.config, writer.uint32(10).fork()).ldelim() + if (message.metadata !== undefined) { + Metadata.encode(message.metadata, writer.uint32(10).fork()).ldelim() } - if (message.plan.length !== 0) { - writer.uint32(18).bytes(message.plan) + for (const v of message.richParameterValues) { + RichParameterValue.encode(v!, writer.uint32(18).fork()).ldelim() + } + for (const v of message.variableValues) { + VariableValue.encode(v!, writer.uint32(26).fork()).ldelim() + } + for (const v of message.gitAuthProviders) { + GitAuthProvider.encode(v!, writer.uint32(34).fork()).ldelim() } return writer }, } -export const Provision_Cancel = { +export const PlanComplete = { encode( - _: Provision_Cancel, + message: PlanComplete, writer: _m0.Writer = _m0.Writer.create(), ): _m0.Writer { + if (message.error !== "") { + writer.uint32(10).string(message.error) + } + for (const v of message.resources) { + Resource.encode(v!, writer.uint32(18).fork()).ldelim() + } + for (const v of message.parameters) { + RichParameter.encode(v!, writer.uint32(26).fork()).ldelim() + } + for (const v of message.gitAuthProviders) { + writer.uint32(34).string(v!) + } return writer }, } -export const Provision_Request = { +export const ApplyRequest = { encode( - message: Provision_Request, + message: ApplyRequest, writer: _m0.Writer = _m0.Writer.create(), ): _m0.Writer { - if (message.plan !== undefined) { - Provision_Plan.encode(message.plan, writer.uint32(10).fork()).ldelim() - } - if (message.apply !== undefined) { - Provision_Apply.encode(message.apply, writer.uint32(18).fork()).ldelim() - } - if (message.cancel !== undefined) { - Provision_Cancel.encode(message.cancel, writer.uint32(26).fork()).ldelim() + if (message.metadata !== undefined) { + Metadata.encode(message.metadata, writer.uint32(10).fork()).ldelim() } return writer }, } -export const Provision_Complete = { +export const ApplyComplete = { encode( - message: Provision_Complete, + message: ApplyComplete, writer: _m0.Writer = _m0.Writer.create(), ): _m0.Writer { if (message.state.length !== 0) { @@ -848,34 +814,76 @@ export const Provision_Complete = { for (const v of message.gitAuthProviders) { writer.uint32(42).string(v!) } - if (message.plan.length !== 0) { - writer.uint32(50).bytes(message.plan) + return writer + }, +} + +export const CancelRequest = { + encode( + _: CancelRequest, + writer: _m0.Writer = _m0.Writer.create(), + ): _m0.Writer { + return writer + }, +} + +export const Request = { + encode( + message: Request, + writer: _m0.Writer = _m0.Writer.create(), + ): _m0.Writer { + if (message.config !== undefined) { + Config.encode(message.config, writer.uint32(10).fork()).ldelim() + } + if (message.parse !== undefined) { + ParseRequest.encode(message.parse, writer.uint32(18).fork()).ldelim() + } + if (message.plan !== undefined) { + PlanRequest.encode(message.plan, writer.uint32(26).fork()).ldelim() + } + if (message.apply !== undefined) { + ApplyRequest.encode(message.apply, writer.uint32(34).fork()).ldelim() + } + if (message.cancel !== undefined) { + CancelRequest.encode(message.cancel, writer.uint32(42).fork()).ldelim() } return writer }, } -export const Provision_Response = { +export const Response = { encode( - message: Provision_Response, + message: Response, writer: _m0.Writer = _m0.Writer.create(), ): _m0.Writer { if (message.log !== undefined) { Log.encode(message.log, writer.uint32(10).fork()).ldelim() } - if (message.complete !== undefined) { - Provision_Complete.encode( - message.complete, - writer.uint32(18).fork(), - ).ldelim() + if (message.parse !== undefined) { + ParseComplete.encode(message.parse, writer.uint32(18).fork()).ldelim() + } + if (message.plan !== undefined) { + PlanComplete.encode(message.plan, writer.uint32(26).fork()).ldelim() + } + if (message.apply !== undefined) { + ApplyComplete.encode(message.apply, writer.uint32(34).fork()).ldelim() } return writer }, } export interface Provisioner { - Parse(request: Parse_Request): Observable - Provision( - request: Observable, - ): Observable + /** + * 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 + * of zero or more Logs, followed by the corresponding complete message (ParseComplete, PlanComplete, + * ApplyComplete). The daemon may then send a new request. A request to apply MUST be preceded by a request plan, + * and the provisioner should store the plan data on the Session after a successful plan, so that the daemon may + * request an apply. If the daemon closes the Session without an apply, the plan data may be safely discarded. + * + * The daemon may send a CancelRequest, asynchronously to ask the provisioner to cancel the previous ParseRequest, + * PlanRequest, or ApplyRequest. The provisioner MUST reply with a complete message corresponding to the request + * that was canceled. If the provisioner has already completed the request, it may ignore the CancelRequest. + */ + Session(request: Observable): Observable } diff --git a/site/e2e/tests/app.spec.ts b/site/e2e/tests/app.spec.ts index b3646fbac1caa..aa69475dc8184 100644 --- a/site/e2e/tests/app.spec.ts +++ b/site/e2e/tests/app.spec.ts @@ -20,7 +20,7 @@ test("app", async ({ context, page }) => { const template = await createTemplate(page, { apply: [ { - complete: { + apply: { resources: [ { agents: [ diff --git a/site/e2e/tests/createWorkspace.spec.ts b/site/e2e/tests/createWorkspace.spec.ts index 10630e2f46ab3..1effc01976651 100644 --- a/site/e2e/tests/createWorkspace.spec.ts +++ b/site/e2e/tests/createWorkspace.spec.ts @@ -21,7 +21,7 @@ test("create workspace", async ({ page }) => { const template = await createTemplate(page, { apply: [ { - complete: { + apply: { resources: [ { name: "example", diff --git a/site/e2e/tests/outdatedAgent.spec.ts b/site/e2e/tests/outdatedAgent.spec.ts index 2b88ea71110df..e10c3f6edb290 100644 --- a/site/e2e/tests/outdatedAgent.spec.ts +++ b/site/e2e/tests/outdatedAgent.spec.ts @@ -15,7 +15,7 @@ test("ssh with agent " + agentVersion, async ({ page }) => { const template = await createTemplate(page, { apply: [ { - complete: { + apply: { resources: [ { agents: [ diff --git a/site/e2e/tests/outdatedCLI.spec.ts b/site/e2e/tests/outdatedCLI.spec.ts index ab143bad27c34..1b09fccf5e13f 100644 --- a/site/e2e/tests/outdatedCLI.spec.ts +++ b/site/e2e/tests/outdatedCLI.spec.ts @@ -15,7 +15,7 @@ test("ssh with client " + clientVersion, async ({ page }) => { const template = await createTemplate(page, { apply: [ { - complete: { + apply: { resources: [ { agents: [ diff --git a/site/e2e/tests/webTerminal.spec.ts b/site/e2e/tests/webTerminal.spec.ts index 492634b293a3e..8869d352d3fc8 100644 --- a/site/e2e/tests/webTerminal.spec.ts +++ b/site/e2e/tests/webTerminal.spec.ts @@ -7,7 +7,7 @@ test("web terminal", async ({ context, page }) => { const template = await createTemplate(page, { apply: [ { - complete: { + apply: { resources: [ { agents: [ diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 7625368589e31..269663580c45d 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -481,8 +481,8 @@ export function waitForBuild(build: TypesGen.WorkspaceBuild) { let latestJobInfo: TypesGen.ProvisionerJob | undefined = undefined while ( - !["succeeded", "canceled"].some( - (status) => latestJobInfo?.status.includes(status), + !["succeeded", "canceled"].some((status) => + latestJobInfo?.status.includes(status), ) ) { const { job } = await getWorkspaceBuildByNumber( From 04127730ced912ddff840d1aab9c4e7c9a78b3dd Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Wed, 23 Aug 2023 13:04:10 +0000 Subject: [PATCH 08/13] More fmt Signed-off-by: Spike Curtis --- site/e2e/helpers.ts | 99 ++++++++++++++++++++++++--------------------- site/src/api/api.ts | 4 +- 2 files changed, 54 insertions(+), 49 deletions(-) diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index ea52356d417e9..aa0e2e32eb9ab 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -353,18 +353,21 @@ const createTemplateVersionTar = async ( responses = {} } if (!responses.parse) { - responses.parse = [{ - parse: {} - }] + responses.parse = [ + { + parse: {}, + }, + ] } if (!responses.apply) { - responses.apply = [{ - apply: {} - }] + responses.apply = [ + { + apply: {}, + }, + ] } if (!responses.plan) { - responses.plan = responses.apply.map( - response => { + responses.plan = responses.apply.map((response) => { if (response.log) { return response } @@ -374,7 +377,7 @@ const createTemplateVersionTar = async ( resources: response.apply?.resources ?? [], parameters: response.apply?.parameters ?? [], gitAuthProviders: response.apply?.gitAuthProviders ?? [], - } + }, } }) } @@ -395,43 +398,45 @@ const createTemplateVersionTar = async ( const fillResource = (resource: RecursivePartial) => { if (resource.agents) { - resource.agents = resource.agents?.map((agent: RecursivePartial) => { - if (agent.apps) { - agent.apps = agent.apps?.map((app: RecursivePartial) => { - return { - command: "", - displayName: "example", - external: false, - icon: "", - sharingLevel: AppSharingLevel.PUBLIC, - slug: "example", - subdomain: false, - url: "", - ...app, - } as App - }) - } - return { - apps: [], - architecture: "amd64", - connectionTimeoutSeconds: 300, - directory: "", - env: {}, - id: randomUUID(), - metadata: [], - motdFile: "", - name: "dev", - operatingSystem: "linux", - shutdownScript: "", - shutdownScriptTimeoutSeconds: 0, - startupScript: "", - startupScriptBehavior: "", - startupScriptTimeoutSeconds: 300, - troubleshootingUrl: "", - token: randomUUID(), - ...agent, - } as Agent - }) + resource.agents = resource.agents?.map( + (agent: RecursivePartial) => { + if (agent.apps) { + agent.apps = agent.apps?.map((app: RecursivePartial) => { + return { + command: "", + displayName: "example", + external: false, + icon: "", + sharingLevel: AppSharingLevel.PUBLIC, + slug: "example", + subdomain: false, + url: "", + ...app, + } as App + }) + } + return { + apps: [], + architecture: "amd64", + connectionTimeoutSeconds: 300, + directory: "", + env: {}, + id: randomUUID(), + metadata: [], + motdFile: "", + name: "dev", + operatingSystem: "linux", + shutdownScript: "", + shutdownScriptTimeoutSeconds: 0, + startupScript: "", + startupScriptBehavior: "", + startupScriptTimeoutSeconds: 300, + troubleshootingUrl: "", + token: randomUUID(), + ...agent, + } as Agent + }, + ) } return { agents: [], @@ -533,7 +538,7 @@ export const echoResponsesWithParameters = ( return { parse: [ { - parse: {} + parse: {}, }, ], plan: [ diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 269663580c45d..7625368589e31 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -481,8 +481,8 @@ export function waitForBuild(build: TypesGen.WorkspaceBuild) { let latestJobInfo: TypesGen.ProvisionerJob | undefined = undefined while ( - !["succeeded", "canceled"].some((status) => - latestJobInfo?.status.includes(status), + !["succeeded", "canceled"].some( + (status) => latestJobInfo?.status.includes(status), ) ) { const { job } = await getWorkspaceBuildByNumber( From d1a9b2a7c2032c89286a670531639fd1ac3129d1 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Thu, 24 Aug 2023 06:08:55 +0000 Subject: [PATCH 09/13] Code review fixes Signed-off-by: Spike Curtis --- coderd/coderdtest/coderdtest.go | 4 +++- provisionerd/proto/provisionerd.proto | 10 +++++----- provisionersdk/proto/provisioner.proto | 26 +++++++++++++------------- provisionersdk/session.go | 21 ++++++++++++++++----- 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go index 4f92665d68e91..a4dea4874717b 100644 --- a/coderd/coderdtest/coderdtest.go +++ b/coderd/coderdtest/coderdtest.go @@ -468,10 +468,12 @@ func NewProvisionerDaemon(t testing.TB, coderAPI *coderd.API) io.Closer { _ = echoServer.Close() cancelFunc() }) + // seems t.TempDir() is not safe to call from a different goroutine + workDir := t.TempDir() go func() { err := echo.Serve(ctx, &provisionersdk.ServeOptions{ Listener: echoServer, - WorkDirectory: t.TempDir(), + WorkDirectory: workDir, Logger: coderAPI.Logger.Named("echo").Leveled(slog.LevelDebug), }) assert.NoError(t, err) diff --git a/provisionerd/proto/provisionerd.proto b/provisionerd/proto/provisionerd.proto index e2cc0b361f87a..8d4fadffc6373 100644 --- a/provisionerd/proto/provisionerd.proto +++ b/provisionerd/proto/provisionerd.proto @@ -45,9 +45,9 @@ message AcquiredJob { TemplateImport template_import = 7; TemplateDryRun template_dry_run = 8; } - // trace_metadata is currently used for tracing information only. It allows - // jobs to be tied to the request that created them. - map trace_metadata = 9; + // trace_metadata is currently used for tracing information only. It allows + // jobs to be tied to the request that created them. + map trace_metadata = 9; } message FailedJob { @@ -113,7 +113,7 @@ message UpdateJobRequest { string job_id = 1; repeated Log logs = 2; repeated provisioner.TemplateVariable template_variables = 4; - repeated provisioner.VariableValue user_variable_values = 5; + repeated provisioner.VariableValue user_variable_values = 5; bytes readme = 6; } @@ -121,7 +121,7 @@ message UpdateJobResponse { reserved 2; bool canceled = 1; - repeated provisioner.VariableValue variable_values = 3; + repeated provisioner.VariableValue variable_values = 3; } message CommitQuotaRequest { diff --git a/provisionersdk/proto/provisioner.proto b/provisionersdk/proto/provisioner.proto index f44b781bead55..5670fbde2675d 100644 --- a/provisionersdk/proto/provisioner.proto +++ b/provisionersdk/proto/provisioner.proto @@ -82,8 +82,8 @@ message InstanceIdentityAuth { } message GitAuthProvider { - string id = 1; - string access_token = 2; + string id = 1; + string access_token = 2; } // Agent represents a running agent on the workspace. @@ -110,15 +110,15 @@ message Agent { string token = 9; string instance_id = 10; } - int32 connection_timeout_seconds = 11; - string troubleshooting_url = 12; - string motd_file = 13; - // Field 14 was bool login_before_ready = 14, now removed. - int32 startup_script_timeout_seconds = 15; - string shutdown_script = 16; - int32 shutdown_script_timeout_seconds = 17; + int32 connection_timeout_seconds = 11; + string troubleshooting_url = 12; + string motd_file = 13; + // Field 14 was bool login_before_ready = 14, now removed. + int32 startup_script_timeout_seconds = 15; + string shutdown_script = 16; + int32 shutdown_script_timeout_seconds = 17; repeated Metadata metadata = 18; - string startup_script_behavior = 19; + string startup_script_behavior = 19; } enum AppSharingLevel { @@ -207,12 +207,12 @@ message ParseRequest { message ParseComplete { string error = 1; repeated TemplateVariable template_variables = 2; - bytes readme = 3; + bytes readme = 3; } // PlanRequest asks the provisioner to plan what resources & parameters it will create message PlanRequest { - Metadata metadata = 1; + Metadata metadata = 1; repeated RichParameterValue rich_parameter_values = 2; repeated VariableValue variable_values = 3; repeated GitAuthProvider git_auth_providers = 4; @@ -229,7 +229,7 @@ message PlanComplete { // 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. message ApplyRequest { - Metadata metadata = 1; + Metadata metadata = 1; } // ApplyComplete indicates a request to apply completed. diff --git a/provisionersdk/session.go b/provisionersdk/session.go index 54418b1b14c7a..3a80a22fcd138 100644 --- a/provisionersdk/session.go +++ b/provisionersdk/session.go @@ -36,14 +36,23 @@ func (p *protoServer) Session(stream proto.DRPCProvisioner_SessionStream) error } sessDir := fmt.Sprintf("Session%p", s) s.WorkDirectory = filepath.Join(p.opts.WorkDirectory, sessDir) - err := os.MkdirAll(s.WorkDirectory, 0o700) + // the WorkDirectory shouldn't exist, but it's possible it does from a restarted process or failed cleanup + err := os.RemoveAll(s.WorkDirectory) + if err != nil { + // RemoveAll returns nil if (as expected) the path doesn't exist. So, if we hit an error, the WorkDirectory + // exists AND we failed to clean it up. + s.Logger.Error(s.Context(), "failed to pre-clean work directory", slog.Error(err)) + return xerrors.Errorf("failed to pre-clean work directory: %w", err) + } + err = os.MkdirAll(s.WorkDirectory, 0o700) if err != nil { return xerrors.Errorf("create work directory %q: %w", s.WorkDirectory, err) } defer func() { + var err error // Cleanup the work directory after execution. for attempt := 0; attempt < 5; attempt++ { - err := os.RemoveAll(s.WorkDirectory) + err = os.RemoveAll(s.WorkDirectory) if err != nil { // On Windows, open files cannot be removed. // When the provisioner daemon is shutting down, @@ -54,8 +63,10 @@ func (p *protoServer) Session(stream proto.DRPCProvisioner_SessionStream) error continue } s.Logger.Debug(s.Context(), "cleaned up work directory") - break + return } + s.Logger.Error(s.Context(), "failed to clean up work directory after multiple attempts", + slog.F("path", s.WorkDirectory), slog.Error(err)) }() req, err := stream.Recv() if err != nil { @@ -70,7 +81,7 @@ func (p *protoServer) Session(stream proto.DRPCProvisioner_SessionStream) error s.logLevel = proto.LogLevel_value[strings.ToUpper(s.Config.ProvisionerLogLevel)] } - err = s.ExtractArchive() + err = s.extractArchive() if err != nil { return xerrors.Errorf("extract archive: %w", err) } @@ -176,7 +187,7 @@ func (s *Session) Context() context.Context { return s.stream.Context() } -func (s *Session) ExtractArchive() error { +func (s *Session) extractArchive() error { ctx := s.Context() s.Logger.Info(ctx, "unpacking template source archive", From ef1820fee440296d530aaa10c3ababb5c27d47e6 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Thu, 24 Aug 2023 07:09:23 +0000 Subject: [PATCH 10/13] new gen; use uuid for session workdir Signed-off-by: Spike Curtis --- provisionerd/proto/provisionerd.pb.go | 4 +-- provisionerd/proto/provisionerd_drpc.pb.go | 2 +- provisionersdk/session.go | 32 +++++++++++----------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/provisionerd/proto/provisionerd.pb.go b/provisionerd/proto/provisionerd.pb.go index a2843bf929c42..018e0f25ac8e1 100644 --- a/provisionerd/proto/provisionerd.pb.go +++ b/provisionerd/proto/provisionerd.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v3.21.12 +// protoc-gen-go v1.30.0 +// protoc v4.23.3 // source: provisionerd/proto/provisionerd.proto package proto diff --git a/provisionerd/proto/provisionerd_drpc.pb.go b/provisionerd/proto/provisionerd_drpc.pb.go index 058af595809b8..ed3155fb21eaa 100644 --- a/provisionerd/proto/provisionerd_drpc.pb.go +++ b/provisionerd/proto/provisionerd_drpc.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-drpc. DO NOT EDIT. -// protoc-gen-go-drpc version: (devel) +// protoc-gen-go-drpc version: v0.0.33 // source: provisionerd/proto/provisionerd.proto package proto diff --git a/provisionersdk/session.go b/provisionersdk/session.go index 3a80a22fcd138..dfcd981ce77f5 100644 --- a/provisionersdk/session.go +++ b/provisionersdk/session.go @@ -11,10 +11,10 @@ import ( "strings" "time" - "cdr.dev/slog" - + "github.com/google/uuid" "golang.org/x/xerrors" + "cdr.dev/slog" "github.com/coder/coder/v2/provisionersdk/proto" ) @@ -29,22 +29,15 @@ type protoServer struct { } func (p *protoServer) Session(stream proto.DRPCProvisioner_SessionStream) error { + sessID := uuid.New().String() s := &Session{ - Logger: p.opts.Logger, + Logger: p.opts.Logger.With(slog.F("session_id", sessID)), stream: stream, server: p.server, } - sessDir := fmt.Sprintf("Session%p", s) + sessDir := fmt.Sprintf("Session%s", sessID) s.WorkDirectory = filepath.Join(p.opts.WorkDirectory, sessDir) - // the WorkDirectory shouldn't exist, but it's possible it does from a restarted process or failed cleanup - err := os.RemoveAll(s.WorkDirectory) - if err != nil { - // RemoveAll returns nil if (as expected) the path doesn't exist. So, if we hit an error, the WorkDirectory - // exists AND we failed to clean it up. - s.Logger.Error(s.Context(), "failed to pre-clean work directory", slog.Error(err)) - return xerrors.Errorf("failed to pre-clean work directory: %w", err) - } - err = os.MkdirAll(s.WorkDirectory, 0o700) + err := os.MkdirAll(s.WorkDirectory, 0o700) if err != nil { return xerrors.Errorf("create work directory %q: %w", s.WorkDirectory, err) } @@ -88,7 +81,7 @@ func (p *protoServer) Session(stream proto.DRPCProvisioner_SessionStream) error return s.handleRequests() } -func (s *Session) requestReader() <-chan *proto.Request { +func (s *Session) requestReader(done <-chan struct{}) <-chan *proto.Request { ch := make(chan *proto.Request) go func() { defer close(ch) @@ -98,14 +91,21 @@ func (s *Session) requestReader() <-chan *proto.Request { s.Logger.Info(s.Context(), "recv done on Session", slog.Error(err)) return } - ch <- req + select { + case ch <- req: + continue + case <-done: + return + } } }() return ch } func (s *Session) handleRequests() error { - requests := s.requestReader() + done := make(chan struct{}) + defer close(done) + requests := s.requestReader(done) planned := false for req := range requests { if req.GetCancel() != nil { From 96e1e64fdc55a87930fa0af4adb8681f14caf716 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Thu, 24 Aug 2023 10:38:37 +0000 Subject: [PATCH 11/13] Revert nix-based gen CI task until dogfood is on nix Signed-off-by: Spike Curtis --- .github/workflows/ci.yaml | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6e02e3fd63fd7..41c7554f5106c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -169,14 +169,38 @@ jobs: with: fetch-depth: 1 - - name: Install Nix - uses: DeterminateSystems/nix-installer-action@v4 + - name: Setup Node + uses: ./.github/actions/setup-node - - name: Run the Magic Nix Cache - uses: DeterminateSystems/magic-nix-cache-action@v2 + - name: Setup Go + uses: ./.github/actions/setup-go + + - name: Setup sqlc + uses: ./.github/actions/setup-sqlc + + - name: go install tools + run: | + go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.30 + go install storj.io/drpc/cmd/protoc-gen-go-drpc@v0.0.33 + go install golang.org/x/tools/cmd/goimports@latest + go install github.com/mikefarah/yq/v4@v4.30.6 + go install github.com/golang/mock/mockgen@v1.6.0 + + - name: Install Protoc + run: | + # protoc must be in lockstep with our dogfood Dockerfile or the + # version in the comments will differ. This is also defined in + # security.yaml + set -x + cd dogfood + DOCKER_BUILDKIT=1 docker build . --target proto -t protoc + protoc_path=/usr/local/bin/protoc + docker run --rm --entrypoint cat protoc /tmp/bin/protoc > $protoc_path + chmod +x $protoc_path + protoc --version - name: make gen - run: "nix-shell --command 'make --output-sync -j -B gen'" + run: "make --output-sync -j -B gen" - name: Check for unstaged files run: ./scripts/check_unstaged.sh From 97621581670e21945c78ac46955c1862727914c7 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Thu, 24 Aug 2023 11:57:27 +0000 Subject: [PATCH 12/13] revert deleting dogfood Docker stuff Signed-off-by: Spike Curtis --- dogfood/Dockerfile | 348 ++++++++++++++++++ dogfood/Makefile | 10 + .../files/etc/apt/apt.conf.d/80-no-recommends | 6 + dogfood/files/etc/apt/apt.conf.d/80-retries | 1 + dogfood/files/etc/apt/preferences.d/docker | 19 + .../files/etc/apt/preferences.d/github-cli | 8 + .../files/etc/apt/preferences.d/google-chrome | 16 + .../files/etc/apt/preferences.d/google-cloud | 19 + dogfood/files/etc/apt/preferences.d/hashicorp | 14 + .../etc/apt/preferences.d/microsoft-edge | 12 + .../files/etc/apt/preferences.d/nodesource | 9 + dogfood/files/etc/apt/preferences.d/ppa | 19 + dogfood/files/etc/apt/preferences.d/yarnpkg | 9 + dogfood/files/etc/apt/sources.list | 3 + .../files/etc/apt/sources.list.d/docker.list | 1 + .../etc/apt/sources.list.d/google-chrome.list | 1 + .../etc/apt/sources.list.d/google-cloud.list | 1 + .../etc/apt/sources.list.d/hashicorp.list | 1 + .../apt/sources.list.d/microsoft-edge.list | 1 + .../etc/apt/sources.list.d/nodesource.list | 1 + .../etc/apt/sources.list.d/postgresql.list | 1 + dogfood/files/etc/apt/sources.list.d/ppa.list | 2 + .../etc/apt/sources.list.d/security.list | 1 + .../files/etc/apt/sources.list.d/yarnpkg.list | 1 + dogfood/files/etc/default/google-chrome | 4 + dogfood/files/etc/default/microsoft-edge-beta | 4 + dogfood/files/etc/docker/daemon.json | 3 + dogfood/files/etc/sudoers.d/nopasswd | 1 + dogfood/files/usr/share/keyrings/ansible.gpg | Bin 0 -> 1132 bytes dogfood/files/usr/share/keyrings/docker.gpg | Bin 0 -> 2760 bytes .../files/usr/share/keyrings/github-cli.gpg | Bin 0 -> 2270 bytes .../usr/share/keyrings/google-chrome.gpg | Bin 0 -> 10640 bytes .../files/usr/share/keyrings/google-cloud.gpg | Bin 0 -> 1210 bytes .../files/usr/share/keyrings/hashicorp.gpg | Bin 0 -> 2879 bytes .../files/usr/share/keyrings/microsoft.gpg | Bin 0 -> 641 bytes dogfood/files/usr/share/keyrings/neovim.gpg | Bin 0 -> 1134 bytes .../files/usr/share/keyrings/nodesource.gpg | Bin 0 -> 2206 bytes .../files/usr/share/keyrings/postgresql.gpg | Bin 0 -> 3494 bytes dogfood/files/usr/share/keyrings/yarnpkg.gpg | Bin 0 -> 10365 bytes dogfood/update-keys.sh | 62 ++++ 40 files changed, 578 insertions(+) create mode 100644 dogfood/Dockerfile create mode 100644 dogfood/Makefile create mode 100644 dogfood/files/etc/apt/apt.conf.d/80-no-recommends create mode 100644 dogfood/files/etc/apt/apt.conf.d/80-retries create mode 100644 dogfood/files/etc/apt/preferences.d/docker create mode 100644 dogfood/files/etc/apt/preferences.d/github-cli create mode 100644 dogfood/files/etc/apt/preferences.d/google-chrome create mode 100644 dogfood/files/etc/apt/preferences.d/google-cloud create mode 100644 dogfood/files/etc/apt/preferences.d/hashicorp create mode 100644 dogfood/files/etc/apt/preferences.d/microsoft-edge create mode 100644 dogfood/files/etc/apt/preferences.d/nodesource create mode 100644 dogfood/files/etc/apt/preferences.d/ppa create mode 100644 dogfood/files/etc/apt/preferences.d/yarnpkg create mode 100644 dogfood/files/etc/apt/sources.list create mode 100644 dogfood/files/etc/apt/sources.list.d/docker.list create mode 100644 dogfood/files/etc/apt/sources.list.d/google-chrome.list create mode 100644 dogfood/files/etc/apt/sources.list.d/google-cloud.list create mode 100644 dogfood/files/etc/apt/sources.list.d/hashicorp.list create mode 100644 dogfood/files/etc/apt/sources.list.d/microsoft-edge.list create mode 100644 dogfood/files/etc/apt/sources.list.d/nodesource.list create mode 100644 dogfood/files/etc/apt/sources.list.d/postgresql.list create mode 100644 dogfood/files/etc/apt/sources.list.d/ppa.list create mode 100644 dogfood/files/etc/apt/sources.list.d/security.list create mode 100644 dogfood/files/etc/apt/sources.list.d/yarnpkg.list create mode 100644 dogfood/files/etc/default/google-chrome create mode 100644 dogfood/files/etc/default/microsoft-edge-beta create mode 100644 dogfood/files/etc/docker/daemon.json create mode 100644 dogfood/files/etc/sudoers.d/nopasswd create mode 100644 dogfood/files/usr/share/keyrings/ansible.gpg create mode 100644 dogfood/files/usr/share/keyrings/docker.gpg create mode 100644 dogfood/files/usr/share/keyrings/github-cli.gpg create mode 100644 dogfood/files/usr/share/keyrings/google-chrome.gpg create mode 100644 dogfood/files/usr/share/keyrings/google-cloud.gpg create mode 100644 dogfood/files/usr/share/keyrings/hashicorp.gpg create mode 100644 dogfood/files/usr/share/keyrings/microsoft.gpg create mode 100644 dogfood/files/usr/share/keyrings/neovim.gpg create mode 100644 dogfood/files/usr/share/keyrings/nodesource.gpg create mode 100644 dogfood/files/usr/share/keyrings/postgresql.gpg create mode 100644 dogfood/files/usr/share/keyrings/yarnpkg.gpg create mode 100755 dogfood/update-keys.sh diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile new file mode 100644 index 0000000000000..8f156bd5152e8 --- /dev/null +++ b/dogfood/Dockerfile @@ -0,0 +1,348 @@ +FROM rust:slim AS rust-utils +# Install rust helper programs +# ENV CARGO_NET_GIT_FETCH_WITH_CLI=true +ENV CARGO_INSTALL_ROOT=/tmp/ +RUN cargo install exa bat ripgrep typos-cli watchexec-cli + +FROM ubuntu:jammy AS go + +RUN apt-get update && apt-get install --yes curl gcc +# Install Go manually, so that we can control the version +ARG GO_VERSION=1.20.7 +RUN mkdir --parents /usr/local/go + +# Boring Go is needed to build FIPS-compliant binaries. +RUN curl --silent --show-error --location \ + "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" \ + -o /usr/local/go.tar.gz + +RUN tar --extract --gzip --directory=/usr/local/go --file=/usr/local/go.tar.gz --strip-components=1 + +ENV PATH=$PATH:/usr/local/go/bin + +# Install Go utilities. +ARG GOPATH="/tmp/" +RUN mkdir --parents "$GOPATH" && \ + # moq for Go tests. + go install github.com/matryer/moq@v0.2.3 && \ + # swag for Swagger doc generation + go install github.com/swaggo/swag/cmd/swag@v1.7.4 && \ + # go-swagger tool to generate the go coder api client + go install github.com/go-swagger/go-swagger/cmd/swagger@v0.28.0 && \ + # goimports for updating imports + go install golang.org/x/tools/cmd/goimports@v0.1.7 && \ + # protoc-gen-go is needed to build sysbox from source + go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.30 && \ + # drpc support for v2 + go install storj.io/drpc/cmd/protoc-gen-go-drpc@v0.0.33 && \ + # migrate for migration support for v2 + go install github.com/golang-migrate/migrate/v4/cmd/migrate@v4.15.1 && \ + # goreleaser for compiling v2 binaries + go install github.com/goreleaser/goreleaser@v1.6.1 && \ + # Install the latest version of gopls for editors that support + # the language server protocol + go install golang.org/x/tools/gopls@latest && \ + # gotestsum makes test output more readable + go install gotest.tools/gotestsum@v1.9.0 && \ + # goveralls collects code coverage metrics from tests + # and sends to Coveralls + go install github.com/mattn/goveralls@v0.0.11 && \ + # kind for running Kubernetes-in-Docker, needed for tests + go install sigs.k8s.io/kind@v0.10.0 && \ + # helm-docs generates our Helm README based on a template and the + # charts and values files + go install github.com/norwoodj/helm-docs/cmd/helm-docs@v1.5.0 && \ + # sqlc for Go code generation + go install github.com/sqlc-dev/sqlc/cmd/sqlc@v1.20.0 && \ + # gcr-cleaner-cli used by CI to prune unused images + go install github.com/sethvargo/gcr-cleaner/cmd/gcr-cleaner-cli@v0.5.1 && \ + # ruleguard for checking custom rules, without needing to run all of + # golangci-lint. Check the go.mod in the release of golangci-lint that + # we're using for the version of go-critic that it embeds, then check + # the version of ruleguard in go-critic for that tag. + go install github.com/quasilyte/go-ruleguard/cmd/ruleguard@v0.3.13 && \ + # go-fuzz for fuzzy testing. they don't publish releases so we rely on latest. + go install github.com/dvyukov/go-fuzz/go-fuzz@latest && \ + go install github.com/dvyukov/go-fuzz/go-fuzz-build@latest && \ + # go-releaser for building 'fat binaries' that work cross-platform + go install github.com/goreleaser/goreleaser@v1.6.1 && \ + go install mvdan.cc/sh/v3/cmd/shfmt@latest && \ + # nfpm is used with `make build` to make release packages + go install github.com/goreleaser/nfpm/v2/cmd/nfpm@v2.16.0 && \ + # yq v4 is used to process yaml files in coder v2. Conflicts with + # yq v3 used in v1. + go install github.com/mikefarah/yq/v4@v4.30.6 && \ + mv /tmp/bin/yq /tmp/bin/yq4 && \ + go install github.com/golang/mock/mockgen@v1.6.0 + +FROM gcr.io/coder-dev-1/alpine:3.18 as proto +WORKDIR /tmp +RUN apk add curl unzip +RUN curl -L -o protoc.zip https://github.com/protocolbuffers/protobuf/releases/download/v23.3/protoc-23.3-linux-x86_64.zip +RUN unzip protoc.zip + +FROM ubuntu:jammy + +SHELL ["/bin/bash", "-c"] + +# Updated certificates are necessary to use the teraswitch mirror. +# This must be ran before copying in configuration since the config replaces +# the default mirror with teraswitch. +RUN apt-get update && apt-get install --yes ca-certificates + +COPY files / + +# Install packages from apt repositories +ARG DEBIAN_FRONTEND="noninteractive" + +RUN apt-get update --quiet && apt-get install --yes \ + apt-transport-https \ + apt-utils \ + bash \ + bash-completion \ + bats \ + bind9-dnsutils \ + build-essential \ + ca-certificates \ + cmake \ + crypto-policies \ + curl \ + fd-find \ + file \ + git \ + gnupg \ + graphviz \ + htop \ + httpie \ + inetutils-tools \ + iproute2 \ + iputils-ping \ + iputils-tracepath \ + jq \ + language-pack-en \ + less \ + lsb-release \ + man \ + meld \ + net-tools \ + openjdk-11-jdk-headless \ + openssh-server \ + openssl \ + libssl-dev \ + pkg-config \ + python3 \ + python3-pip \ + rsync \ + shellcheck \ + strace \ + sudo \ + tcptraceroute \ + termshark \ + traceroute \ + vim \ + wget \ + xauth \ + zip \ + ncdu \ + cargo \ + asciinema \ + zsh \ + ansible \ + neovim \ + google-cloud-sdk \ + google-cloud-sdk-datastore-emulator \ + kubectl \ + postgresql-13 \ + containerd.io \ + docker-ce \ + docker-ce-cli \ + docker-compose-plugin \ + packer \ + terraform \ + fish \ + unzip \ + zstd \ + screen \ + gettext-base && \ + # Delete package cache to avoid consuming space in layer + apt-get clean && \ + # Configure FIPS-compliant policies + update-crypto-policies --set FIPS + +# Install the docker buildx component. +RUN DOCKER_BUILDX_VERSION=$(curl -s "https://api.github.com/repos/docker/buildx/releases/latest" | grep '"tag_name":' | sed -E 's/.*"(v[^"]+)".*/\1/') && \ + mkdir -p /usr/local/lib/docker/cli-plugins && \ + curl -Lo /usr/local/lib/docker/cli-plugins/docker-buildx "https://github.com/docker/buildx/releases/download/${DOCKER_BUILDX_VERSION}/buildx-${DOCKER_BUILDX_VERSION}.linux-amd64" && \ + chmod a+x /usr/local/lib/docker/cli-plugins/docker-buildx + +# See https://github.com/cli/cli/issues/6175#issuecomment-1235984381 for proof +# the apt repository is unreliable +RUN GH_CLI_VERSION=$(curl -s "https://api.github.com/repos/cli/cli/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/') && \ + curl -L https://github.com/cli/cli/releases/download/v${GH_CLI_VERSION}/gh_${GH_CLI_VERSION}_linux_amd64.deb -o gh.deb && \ + dpkg -i gh.deb && \ + rm gh.deb + +# Install Lazygit +# See https://github.com/jesseduffield/lazygit#ubuntu +RUN LAZYGIT_VERSION=$(curl -s "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v*([^"]+)".*/\1/') && \ + curl -Lo lazygit.tar.gz "https://github.com/jesseduffield/lazygit/releases/latest/download/lazygit_${LAZYGIT_VERSION}_Linux_x86_64.tar.gz" && \ + tar xf lazygit.tar.gz -C /usr/local/bin lazygit + +# Install frontend utilities +RUN apt-get update && \ + # Node.js (from nodesource) and Yarn (from yarnpkg) + curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - &&\ + apt-get install --yes --quiet \ + nodejs yarn \ + # Install browsers for e2e testing + google-chrome-stable microsoft-edge-beta && \ + # Pre-install system dependencies that Playwright needs. npx doesn't work here + # for some reason. See https://github.com/microsoft/playwright-cli/issues/136 + npm i -g playwright@1.36.2 pnpm@^8 && playwright install-deps && \ + npm cache clean --force + +# Ensure PostgreSQL binaries are in the users $PATH. +RUN update-alternatives --install /usr/local/bin/initdb initdb /usr/lib/postgresql/13/bin/initdb 100 && \ + update-alternatives --install /usr/local/bin/postgres postgres /usr/lib/postgresql/13/bin/postgres 100 + +# Create links for injected dependencies +RUN ln --symbolic /var/tmp/coder/coder-cli/coder /usr/local/bin/coder && \ + ln --symbolic /var/tmp/coder/code-server/bin/code-server /usr/local/bin/code-server + +# Disable the PostgreSQL systemd service. +# Coder uses a custom timescale container to test the database instead. +RUN systemctl disable \ + postgresql + +# Configure systemd services for CVMs +RUN systemctl enable \ + docker \ + ssh + +# Install tools with published releases, where that is the +# preferred/recommended installation method. +ARG CLOUD_SQL_PROXY_VERSION=2.2.0 \ + DIVE_VERSION=0.10.0 \ + DOCKER_GCR_VERSION=2.1.8 \ + GOLANGCI_LINT_VERSION=1.52.2 \ + GRYPE_VERSION=0.61.1 \ + HELM_VERSION=3.12.0 \ + KUBE_LINTER_VERSION=0.6.3 \ + KUBECTX_VERSION=0.9.4 \ + STRIPE_VERSION=1.14.5 \ + TERRAGRUNT_VERSION=0.45.11 \ + TRIVY_VERSION=0.41.0 + +# cloud_sql_proxy, for connecting to cloudsql instances +# the upstream go.mod prevents this from being installed with go install +RUN curl --silent --show-error --location --output /usr/local/bin/cloud_sql_proxy "https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v${CLOUD_SQL_PROXY_VERSION}/cloud-sql-proxy.linux.amd64" && \ + chmod a=rx /usr/local/bin/cloud_sql_proxy && \ + # dive for scanning image layer utilization metrics in CI + curl --silent --show-error --location "https://github.com/wagoodman/dive/releases/download/v${DIVE_VERSION}/dive_${DIVE_VERSION}_linux_amd64.tar.gz" | \ + tar --extract --gzip --directory=/usr/local/bin --file=- dive && \ + # docker-credential-gcr is a Docker credential helper for pushing/pulling + # images from Google Container Registry and Artifact Registry + curl --silent --show-error --location "https://github.com/GoogleCloudPlatform/docker-credential-gcr/releases/download/v${DOCKER_GCR_VERSION}/docker-credential-gcr_linux_amd64-${DOCKER_GCR_VERSION}.tar.gz" | \ + tar --extract --gzip --directory=/usr/local/bin --file=- docker-credential-gcr && \ + # golangci-lint performs static code analysis for our Go code + curl --silent --show-error --location "https://github.com/golangci/golangci-lint/releases/download/v${GOLANGCI_LINT_VERSION}/golangci-lint-${GOLANGCI_LINT_VERSION}-linux-amd64.tar.gz" | \ + tar --extract --gzip --directory=/usr/local/bin --file=- --strip-components=1 "golangci-lint-${GOLANGCI_LINT_VERSION}-linux-amd64/golangci-lint" && \ + # Anchore Grype for scanning container images for security issues + curl --silent --show-error --location "https://github.com/anchore/grype/releases/download/v${GRYPE_VERSION}/grype_${GRYPE_VERSION}_linux_amd64.tar.gz" | \ + tar --extract --gzip --directory=/usr/local/bin --file=- grype && \ + # Helm is necessary for deploying Coder + curl --silent --show-error --location "https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz" | \ + tar --extract --gzip --directory=/usr/local/bin --file=- --strip-components=1 linux-amd64/helm && \ + # kube-linter for linting Kubernetes objects, including those + # that Helm generates from our charts + curl --silent --show-error --location "https://github.com/stackrox/kube-linter/releases/download/${KUBE_LINTER_VERSION}/kube-linter-linux" --output /usr/local/bin/kube-linter && \ + # kubens and kubectx for managing Kubernetes namespaces and contexts + curl --silent --show-error --location "https://github.com/ahmetb/kubectx/releases/download/v${KUBECTX_VERSION}/kubectx_v${KUBECTX_VERSION}_linux_x86_64.tar.gz" | \ + tar --extract --gzip --directory=/usr/local/bin --file=- kubectx && \ + curl --silent --show-error --location "https://github.com/ahmetb/kubectx/releases/download/v${KUBECTX_VERSION}/kubens_v${KUBECTX_VERSION}_linux_x86_64.tar.gz" | \ + tar --extract --gzip --directory=/usr/local/bin --file=- kubens && \ + # stripe for coder.com billing API + curl --silent --show-error --location "https://github.com/stripe/stripe-cli/releases/download/v${STRIPE_VERSION}/stripe_${STRIPE_VERSION}_linux_x86_64.tar.gz" | \ + tar --extract --gzip --directory=/usr/local/bin --file=- stripe && \ + # terragrunt for running Terraform and Terragrunt files + curl --silent --show-error --location --output /usr/local/bin/terragrunt "https://github.com/gruntwork-io/terragrunt/releases/download/v${TERRAGRUNT_VERSION}/terragrunt_linux_amd64" && \ + chmod a=rx /usr/local/bin/terragrunt && \ + # AquaSec Trivy for scanning container images for security issues + curl --silent --show-error --location "https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz" | \ + tar --extract --gzip --directory=/usr/local/bin --file=- trivy + +# Add Vercel globally. We can't install it in packages.json, because it +# includes Go files which make golangci-lint unhappy. +RUN yarn global add --prefix=/usr/local \ + vercel \ + typescript \ + typescript-language-server \ + prettier && \ + yarn cache clean + +# We use yq during "make deploy" to manually substitute out fields in +# our helm values.yaml file. See https://github.com/helm/helm/issues/3141 +# +# TODO: update to 4.x, we can't do this now because it included breaking +# changes (yq w doesn't work anymore) +# RUN curl --silent --show-error --location "https://github.com/mikefarah/yq/releases/download/v4.9.0/yq_linux_amd64.tar.gz" | \ +# tar --extract --gzip --directory=/usr/local/bin --file=- ./yq_linux_amd64 && \ +# mv /usr/local/bin/yq_linux_amd64 /usr/local/bin/yq + +RUN curl --silent --show-error --location --output /usr/local/bin/yq "https://github.com/mikefarah/yq/releases/download/3.3.0/yq_linux_amd64" && \ + chmod a=rx /usr/local/bin/yq + +# Install GoLand. +RUN mkdir --parents /usr/local/goland && \ + curl --silent --show-error --location "https://download.jetbrains.com/go/goland-2021.2.tar.gz" | \ + tar --extract --gzip --directory=/usr/local/goland --file=- --strip-components=1 && \ + ln --symbolic /usr/local/goland/bin/goland.sh /usr/local/bin/goland + +# Install Antlrv4, needed to generate paramlang lexer/parser +RUN curl --silent --show-error --location --output /usr/local/lib/antlr-4.9.2-complete.jar "https://www.antlr.org/download/antlr-4.9.2-complete.jar" +ENV CLASSPATH="/usr/local/lib/antlr-4.9.2-complete.jar:${PATH}" + +# Add coder user and allow use of docker/sudo +RUN useradd coder \ + --create-home \ + --shell=/bin/bash \ + --groups=docker \ + --uid=1000 \ + --user-group + +# Adjust OpenSSH config +RUN echo "PermitUserEnvironment yes" >>/etc/ssh/sshd_config && \ + echo "X11Forwarding yes" >>/etc/ssh/sshd_config && \ + echo "X11UseLocalhost no" >>/etc/ssh/sshd_config + +# We avoid copying the extracted directory since COPY slows to minutes when there +# are a lot of small files. +COPY --from=go /usr/local/go.tar.gz /usr/local/go.tar.gz +RUN mkdir /usr/local/go && \ + tar --extract --gzip --directory=/usr/local/go --file=/usr/local/go.tar.gz --strip-components=1 + +ENV PATH=$PATH:/usr/local/go/bin + +RUN update-alternatives --install /usr/local/bin/gofmt gofmt /usr/local/go/bin/gofmt 100 + +COPY --from=go /tmp/bin /usr/local/bin +COPY --from=rust-utils /tmp/bin /usr/local/bin +COPY --from=proto /tmp/bin /usr/local/bin +COPY --from=proto /tmp/include /usr/local/bin/include + +USER coder + +# Ensure go bins are in the 'coder' user's path. Note that no go bins are +# installed in this docker file, as they'd be mounted over by the persistent +# home volume. +ENV PATH="/home/coder/go/bin:${PATH}" + +# This setting prevents Go from using the public checksum database for +# our module path prefixes. It is required because these are in private +# repositories that require authentication. +# +# For details, see: https://golang.org/ref/mod#private-modules +ENV GOPRIVATE="coder.com,cdr.dev,go.coder.com,github.com/cdr,github.com/coder" + +# Increase memory allocation to NodeJS +ENV NODE_OPTIONS="--max-old-space-size=8192" diff --git a/dogfood/Makefile b/dogfood/Makefile new file mode 100644 index 0000000000000..061530f50dd45 --- /dev/null +++ b/dogfood/Makefile @@ -0,0 +1,10 @@ +.PHONY: docker-build docker-push + +branch=$(shell git rev-parse --abbrev-ref HEAD) +build_tag=codercom/oss-dogfood:${branch} + +build: + DOCKER_BUILDKIT=1 docker build . -t ${build_tag} + +push: build + docker push ${build_tag} diff --git a/dogfood/files/etc/apt/apt.conf.d/80-no-recommends b/dogfood/files/etc/apt/apt.conf.d/80-no-recommends new file mode 100644 index 0000000000000..8cb79c96386c4 --- /dev/null +++ b/dogfood/files/etc/apt/apt.conf.d/80-no-recommends @@ -0,0 +1,6 @@ +// Do not install recommended packages by default +APT::Install-Recommends "0"; + +// Do not install suggested packages by default (this is already +// the Ubuntu default) +APT::Install-Suggests "0"; diff --git a/dogfood/files/etc/apt/apt.conf.d/80-retries b/dogfood/files/etc/apt/apt.conf.d/80-retries new file mode 100644 index 0000000000000..d7ee5185258ec --- /dev/null +++ b/dogfood/files/etc/apt/apt.conf.d/80-retries @@ -0,0 +1 @@ +APT::Acquire::Retries "3"; diff --git a/dogfood/files/etc/apt/preferences.d/docker b/dogfood/files/etc/apt/preferences.d/docker new file mode 100644 index 0000000000000..a92c0abb03d7c --- /dev/null +++ b/dogfood/files/etc/apt/preferences.d/docker @@ -0,0 +1,19 @@ +# Ignore all packages from this repository by default +Package: * +Pin: origin download.docker.com +Pin-Priority: 1 + +# Docker Community Edition +Package: docker-ce +Pin: origin download.docker.com +Pin-Priority: 500 + +# Docker command-line tool +Package: docker-ce-cli +Pin: origin download.docker.com +Pin-Priority: 500 + +# containerd runtime +Package: containerd.io +Pin: origin download.docker.com +Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/github-cli b/dogfood/files/etc/apt/preferences.d/github-cli new file mode 100644 index 0000000000000..d2dce9f5f3097 --- /dev/null +++ b/dogfood/files/etc/apt/preferences.d/github-cli @@ -0,0 +1,8 @@ +# Ignore all packages from this repository by default +Package: * +Pin: origin cli.github.com +Pin-Priority: 1 + +Package: gh +Pin: origin cli.github.com +Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/google-chrome b/dogfood/files/etc/apt/preferences.d/google-chrome new file mode 100644 index 0000000000000..4551ec390ff20 --- /dev/null +++ b/dogfood/files/etc/apt/preferences.d/google-chrome @@ -0,0 +1,16 @@ +# Ignore all packages from this repository by default +Package: * +Pin: origin dl.google.com +Pin-Priority: 1 + +Package: google-chrome-stable +Pin: origin dl.google.com +Pin-Priority: 500 + +Package: google-chrome-beta +Pin: origin dl.google.com +Pin-Priority: 500 + +Package: google-chrome-unstable +Pin: origin dl.google.com +Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/google-cloud b/dogfood/files/etc/apt/preferences.d/google-cloud new file mode 100644 index 0000000000000..637b0e9bb3c51 --- /dev/null +++ b/dogfood/files/etc/apt/preferences.d/google-cloud @@ -0,0 +1,19 @@ +# Ignore all packages from this repository by default +Package: * +Pin: origin packages.cloud.google.com +Pin-Priority: 1 + +# Google Cloud SDK for gcloud and gsutil CLI tools +Package: google-cloud-sdk +Pin: origin packages.cloud.google.com +Pin-Priority: 500 + +# Datastore emulator for working with the licensor +Package: google-cloud-sdk-datastore-emulator +Pin: origin packages.cloud.google.com +Pin-Priority: 500 + +# Kubectl for working with Kubernetes (GKE) +Package: kubectl +Pin: origin packages.cloud.google.com +Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/hashicorp b/dogfood/files/etc/apt/preferences.d/hashicorp new file mode 100644 index 0000000000000..4323f331cc722 --- /dev/null +++ b/dogfood/files/etc/apt/preferences.d/hashicorp @@ -0,0 +1,14 @@ +# Ignore all packages from this repository by default +Package: * +Pin: origin apt.releases.hashicorp.com +Pin-Priority: 1 + +# Packer for creating virtual machine disk images +Package: packer +Pin: origin apt.releases.hashicorp.com +Pin-Priority: 500 + +# Terraform for managing infrastructure +Package: terraform +Pin: origin apt.releases.hashicorp.com +Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/microsoft-edge b/dogfood/files/etc/apt/preferences.d/microsoft-edge new file mode 100644 index 0000000000000..2441961adac38 --- /dev/null +++ b/dogfood/files/etc/apt/preferences.d/microsoft-edge @@ -0,0 +1,12 @@ +# Ignore all packages from this repository by default +Package: * +Pin: origin packages.microsoft.com +Pin-Priority: 1 + +Package: microsoft-edge-beta +Pin: origin packages.microsoft.com +Pin-Priority: 500 + +Package: microsoft-edge-dev +Pin: origin packages.microsoft.com +Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/nodesource b/dogfood/files/etc/apt/preferences.d/nodesource new file mode 100644 index 0000000000000..de55d5553411e --- /dev/null +++ b/dogfood/files/etc/apt/preferences.d/nodesource @@ -0,0 +1,9 @@ +# Ignore all packages from this repository by default +Package: * +Pin: origin deb.nodesource.com +Pin-Priority: 1 + +# Node.js for building the frontend +Package: nodejs +Pin: origin deb.nodesource.com +Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/ppa b/dogfood/files/etc/apt/preferences.d/ppa new file mode 100644 index 0000000000000..1dc9da8f9fffc --- /dev/null +++ b/dogfood/files/etc/apt/preferences.d/ppa @@ -0,0 +1,19 @@ +# Ignore all packages from this repository by default +Package: * +Pin: origin ppa.launchpad.net +Pin-Priority: 1 + +# Ansible +Package: ansible-base +Pin: origin ppa.launchpad.net +Pin-Priority: 500 + +# Neovim +Package: neovim +Pin: origin ppa.launchpad.net +Pin-Priority: 500 + +# Neovim Runtime +Package: neovim-runtime +Pin: origin ppa.launchpad.net +Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/yarnpkg b/dogfood/files/etc/apt/preferences.d/yarnpkg new file mode 100644 index 0000000000000..7237fcad5c356 --- /dev/null +++ b/dogfood/files/etc/apt/preferences.d/yarnpkg @@ -0,0 +1,9 @@ +# Ignore all packages from this repository by default +Package: * +Pin: origin dl.yarnpkg.com +Pin-Priority: 1 + +# Yarn for managing Node.js packages +Package: yarn +Pin: origin dl.yarnpkg.com +Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/sources.list b/dogfood/files/etc/apt/sources.list new file mode 100644 index 0000000000000..745bcefcf2b0c --- /dev/null +++ b/dogfood/files/etc/apt/sources.list @@ -0,0 +1,3 @@ +deb https://mirror.pit.teraswitch.com/ubuntu/ jammy main restricted universe +deb https://mirror.pit.teraswitch.com/ubuntu/ jammy-updates main restricted universe +deb https://mirror.pit.teraswitch.com/ubuntu/ jammy-backports main restricted universe diff --git a/dogfood/files/etc/apt/sources.list.d/docker.list b/dogfood/files/etc/apt/sources.list.d/docker.list new file mode 100644 index 0000000000000..f00cada1ad16e --- /dev/null +++ b/dogfood/files/etc/apt/sources.list.d/docker.list @@ -0,0 +1 @@ +deb [signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu jammy stable diff --git a/dogfood/files/etc/apt/sources.list.d/google-chrome.list b/dogfood/files/etc/apt/sources.list.d/google-chrome.list new file mode 100644 index 0000000000000..8dd71926f26df --- /dev/null +++ b/dogfood/files/etc/apt/sources.list.d/google-chrome.list @@ -0,0 +1 @@ +deb [signed-by=/usr/share/keyrings/google-chrome.gpg] https://dl.google.com/linux/chrome/deb/ stable main diff --git a/dogfood/files/etc/apt/sources.list.d/google-cloud.list b/dogfood/files/etc/apt/sources.list.d/google-cloud.list new file mode 100644 index 0000000000000..24df98effea28 --- /dev/null +++ b/dogfood/files/etc/apt/sources.list.d/google-cloud.list @@ -0,0 +1 @@ +deb [signed-by=/usr/share/keyrings/google-cloud.gpg] https://packages.cloud.google.com/apt cloud-sdk main diff --git a/dogfood/files/etc/apt/sources.list.d/hashicorp.list b/dogfood/files/etc/apt/sources.list.d/hashicorp.list new file mode 100644 index 0000000000000..6e60053905ec7 --- /dev/null +++ b/dogfood/files/etc/apt/sources.list.d/hashicorp.list @@ -0,0 +1 @@ +deb [signed-by=/usr/share/keyrings/hashicorp.gpg] https://apt.releases.hashicorp.com jammy main diff --git a/dogfood/files/etc/apt/sources.list.d/microsoft-edge.list b/dogfood/files/etc/apt/sources.list.d/microsoft-edge.list new file mode 100644 index 0000000000000..f0c036f79a5c5 --- /dev/null +++ b/dogfood/files/etc/apt/sources.list.d/microsoft-edge.list @@ -0,0 +1 @@ +deb [signed-by=/usr/share/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/edge stable main diff --git a/dogfood/files/etc/apt/sources.list.d/nodesource.list b/dogfood/files/etc/apt/sources.list.d/nodesource.list new file mode 100644 index 0000000000000..a328c2c3c47dc --- /dev/null +++ b/dogfood/files/etc/apt/sources.list.d/nodesource.list @@ -0,0 +1 @@ +deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_16.x jammy main diff --git a/dogfood/files/etc/apt/sources.list.d/postgresql.list b/dogfood/files/etc/apt/sources.list.d/postgresql.list new file mode 100644 index 0000000000000..10262f3e64a10 --- /dev/null +++ b/dogfood/files/etc/apt/sources.list.d/postgresql.list @@ -0,0 +1 @@ +deb [signed-by=/usr/share/keyrings/postgresql.gpg] https://apt.postgresql.org/pub/repos/apt jammy-pgdg main diff --git a/dogfood/files/etc/apt/sources.list.d/ppa.list b/dogfood/files/etc/apt/sources.list.d/ppa.list new file mode 100644 index 0000000000000..e817c20915cb1 --- /dev/null +++ b/dogfood/files/etc/apt/sources.list.d/ppa.list @@ -0,0 +1,2 @@ +deb [signed-by=/usr/share/keyrings/ansible.gpg] https://ppa.launchpadcontent.net/ansible/ansible/ubuntu focal main +deb [signed-by=/usr/share/keyrings/neovim.gpg] https://ppa.launchpadcontent.net/neovim-ppa/stable/ubuntu focal main diff --git a/dogfood/files/etc/apt/sources.list.d/security.list b/dogfood/files/etc/apt/sources.list.d/security.list new file mode 100644 index 0000000000000..1f3dae8d09b19 --- /dev/null +++ b/dogfood/files/etc/apt/sources.list.d/security.list @@ -0,0 +1 @@ +deb http://security.ubuntu.com/ubuntu/ jammy-security main restricted universe diff --git a/dogfood/files/etc/apt/sources.list.d/yarnpkg.list b/dogfood/files/etc/apt/sources.list.d/yarnpkg.list new file mode 100644 index 0000000000000..ada8a06f7b9b2 --- /dev/null +++ b/dogfood/files/etc/apt/sources.list.d/yarnpkg.list @@ -0,0 +1 @@ +deb [signed-by=/usr/share/keyrings/yarnpkg.gpg] https://dl.yarnpkg.com/debian/ stable main diff --git a/dogfood/files/etc/default/google-chrome b/dogfood/files/etc/default/google-chrome new file mode 100644 index 0000000000000..8620a6054380a --- /dev/null +++ b/dogfood/files/etc/default/google-chrome @@ -0,0 +1,4 @@ +# These settings are required to prevent the postinst script +# from modifying /etc/apt/sources.list.d +repo_add_once="false" +repo_reenable_on_distupgrade="false" diff --git a/dogfood/files/etc/default/microsoft-edge-beta b/dogfood/files/etc/default/microsoft-edge-beta new file mode 100644 index 0000000000000..8620a6054380a --- /dev/null +++ b/dogfood/files/etc/default/microsoft-edge-beta @@ -0,0 +1,4 @@ +# These settings are required to prevent the postinst script +# from modifying /etc/apt/sources.list.d +repo_add_once="false" +repo_reenable_on_distupgrade="false" diff --git a/dogfood/files/etc/docker/daemon.json b/dogfood/files/etc/docker/daemon.json new file mode 100644 index 0000000000000..8e19eeeec15b8 --- /dev/null +++ b/dogfood/files/etc/docker/daemon.json @@ -0,0 +1,3 @@ +{ + "registry-mirrors": ["https://mirror.gcr.io"] +} diff --git a/dogfood/files/etc/sudoers.d/nopasswd b/dogfood/files/etc/sudoers.d/nopasswd new file mode 100644 index 0000000000000..3283f4455630c --- /dev/null +++ b/dogfood/files/etc/sudoers.d/nopasswd @@ -0,0 +1 @@ +coder ALL=(ALL) NOPASSWD:ALL diff --git a/dogfood/files/usr/share/keyrings/ansible.gpg b/dogfood/files/usr/share/keyrings/ansible.gpg new file mode 100644 index 0000000000000000000000000000000000000000..1731dd2b2fbd7ce251ad1b2a53f7df432f40ba60 GIT binary patch literal 1132 zcmV-y1e5#5!A%5Hmu)Zs5CF<8#y2sBavX?)67L*C?G(=zXq7e@f6Q6auif(;)LZod zJu=nD{xl;si4m1N>|mHxbs=?y#0s%cDFcoXWGuiOPPcBqgGtD(O&)chTnV3O_vTKp zpxjBtjm2l2l)Co$f!&#ZUZx+mr|if+XiX)imRGOaN{wFzF5qf*MMMWR-!r_9)GT8n z9-skmj@@r=PeO_JMTAEoMON^=mLX&{p9PrVXI@k~>Eol0;1Wto(EAo0j!ob9JLZv$ zz{J9ga|)i0iWfLtD7Lfx2pcwfa@C_G1MjY`Lz6(awYWneCUowKp!;(c|LRENDJuV@}J^R10+K>bBPj0 zCcgwPd7G4u#uSnVISiLz>kj2k1P55=&JfyHmd(KqdSL^A$;r(RK;Xi~)S07(S1`Hx zluz`k@CoV<@SfH`dGGH;tTOf>%sFH)iWJCW^83^D=M##Vb)#E2kuO`HOHZMJPPY`) z#rAzJVN>~#YhaCw6qRIee66;(wewmmFwLqfI#xM7Uyj4+Unp~Z9?dnFy^Ep&k9z1@*%FAsQAQg_q^ zZA|2Ax}@E=%BDtciOPD+c(7l!ho;1z9^v?+=mW{bPK7@|z`h3!+#5lH>mC;e zAZw{ca%yxWx*r-8+j=+B_0_#@aD^lrQGYcRci@}xrY_B1bATdXsNhK*{R`_5@Snvl z%@^X(#j_I0E(`LpP@0t-%adrgYf0nv{mkf^m#uEZhfVP0mH+ABM$$9YYGhc7uU_zb zLfwi01ixZuFJvRqgLiooRMNo7-bQbSnxUT8je#Ug{poZ{T)y9ck!Lmb=J$T22%i1(LzY!TWhePHBrdo)WGPY3)h z7C#hPORz)L!-36Ks;a^piJc|8(PTGnSad{%|NB2-0#?2=Ng~I(^p!6?WEWF|1MY|_ yf9W@2In1 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 literal 0 HcmV?d00001 diff --git a/dogfood/files/usr/share/keyrings/google-chrome.gpg b/dogfood/files/usr/share/keyrings/google-chrome.gpg new file mode 100644 index 0000000000000000000000000000000000000000..cee005a7386d9c20b1500ed18f58e98d5ecb7468 GIT binary patch literal 10640 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 NoHjgY=A3`m{~vJw|Kb1u literal 0 HcmV?d00001 diff --git a/dogfood/files/usr/share/keyrings/google-cloud.gpg b/dogfood/files/usr/share/keyrings/google-cloud.gpg new file mode 100644 index 0000000000000000000000000000000000000000..0f478144f1491ce0e6668faf181eb8a7f24a208a GIT binary patch literal 1210 zcmV;r1V#JCz)b{Vh_%!K2mscYq|IbT7J+=b+*`^Oj$cN)IJ9G0;1{?}mAAo~T({7p z@JRBJPSW&4=qGU6)ec&2A)J#VmCA#C z|M1{S^3O7Tn&fI1N7}adYPQ9-dtC8TNI+&0-YS5c37a=4rb<3Z*5_8X=5N$X=iR}Zf77%WqBYd zV{C7AWG!-GaCCKYWi4}QXKrb3XDw@Gc`Y(9GBPbNGc7PTEigD=Ffm^+F)na*VkyGF zVgwTb2mlrZ0%C}@)Cmx^J;)6c?e7Hw8v_Cv0RRBOs0aXjKodwH-O$)Q+G-l#k-nP6 z-g(UI5z^V~isDhA@#r?{D>{&`^`(q5^Z*Feq{hq1#6f&HM)QRxBLNe^^t$sHNzEqccHSo% zWsaw#U7E)!v2s_x`5>lsuP6)$+R`k5+AN^`i?ZAY*DKFab29GU>|zfq z_$t}Yd{Gm@ThG7^`GAXx1RftieU>Qkk}w6Y>tP2%D?0A$y8~GIYu!JmKzju)uj)x? zh{SvDEbx#-6}|z)m%#-4gluH7ZY~ZyLT^FOIb521d65cueP!h;<8zGj#n0vikf07;k#0EH9e{n2CZR@D7O*RDY%Wt_zHoYaA-|F+zb ztzM99RzL(CpW>Dy20yYatT)@uKm3)htg12E?8K{BU0nB_L~;T~=yeu1bkd7jL+l0@ zc^L1E1ukma{Wm(HKA4kQvSzePTx1NxT5T!@PC$-o`; z(ghh8M)_;m7^ArH11OC^u!uzAl7Me+BshQcv zn$%;AzR1N#hH7P2I|9&cO8(!2FwNJAb;A68tNAPs6q8G($>rU`APVqOkg_aD`xbA{ YvDCB4XX2J{8xPZ_^SyA%2cipL&5QI%SpWb4 literal 0 HcmV?d00001 diff --git a/dogfood/files/usr/share/keyrings/hashicorp.gpg b/dogfood/files/usr/share/keyrings/hashicorp.gpg new file mode 100644 index 0000000000000000000000000000000000000000..674dd40c4219e7f397ea58978a945ccf952b79ff GIT binary patch literal 2879 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 F;BR8aVf_FA literal 0 HcmV?d00001 diff --git a/dogfood/files/usr/share/keyrings/microsoft.gpg b/dogfood/files/usr/share/keyrings/microsoft.gpg new file mode 100644 index 0000000000000000000000000000000000000000..0cffae08d061d6ae8959b4442dd2dbce26c340e8 GIT binary patch literal 641 zcmV-{0)G9O0SyFJF<6WN2mrt;hGAw>aTw8-&ZU0T;kCvj9-@p2hRX&3tKIp#mk44K zWSkQ%c4{HQA}s#tsn;1=(LHS^JIEF`F{wkR(&D>9o|7yP=~Y+NKK3;C`4axI=rYyq zrB<*k)BskBDEsDx5Yd^pAvz|*XxLN^Rs1tKcJz?E$yQpt@e`p4a|{c zMCET7wg8i5k#M`dMmXStEMdYRelqXC@i+Karv74@Qsaue67_2{MmJAUtPq zXLDs^b#iHRc|dJxV{&hEZ)S8ZV{dIfi2*eP69EDM9|ZzdF<6WO8v_Ol2?z%R0t6KT z2m=Ea0s#UZ0Rk6*0162Z>pqmNz7i?V8k-0IeXlDmy&evAAJ<zH{duFkO6N3 z&j)GB_6-&>FO*4L(_oK+UEBCNPtqruWb}jtrH<)Fo&NESBL93CCK@(!cM{sFL# zl3lGc*OY}TPJY89Y`5yhtDjdGdR`sF=-obeZ6|&)Q?JB*^tR`Hs`bI;7%7s23ub3m z2fb~VjF|gS`dseajhzmSVAqkLq?Lzd-||b!CPpP=s@8rTvf6|&1HsVQ^$#~j*4_B z^wo#Yk$Y085z>xnXPh*YyXCM?X!Pz34&qQJWF>^y#mQ?Jy36e=iZ;jd+pzLw&Z~qp z9J+_wM!!;)U9TJ>|{QL461&b!QjK$m6TSoI*Z?BZZUGed_%I zq@w4C+YUK7V*G66P1FMCB=1(Q0v{fk--rSn_+rv#2P+VoJ}C|S6~o~oM@taQ>Mq^X z*FGXUmgmLfb&~)Q0RREbAxvR)ZewV0VPqgsP(dJOZ*m|`Wp8$AZ6HukK_FCRVQs>} zcmxvx0stZf0#u33qXHWP1`7!Y2Ll2I6$k|8!UY)ML z?f{O&>KSG%w!M&okwu6`ShMAUxoz)SabFLueiM$KoUDI zx!sM%wVVU={@k`?+zS~>77|toi>_NThL3?qSo_W5_Z>u62g!RHUcPk*2{p^0b>g{i ziDBYyHCIbR6O^dmyn%PY9&_=gKp zB2Dn)pL>}Y{`@YqQu8<*4#ucVWl@T&o5F~wef_KAIEV1sIIj~eCi0EgcN%>#{rn3}1Kqr1_6^$8%9?VPE|Luu{wV46z1K0qY z)(wi}yw|tNeAvYIe{9Y+h3YF|_DbZK{aU{)%!HvAI@XQ2l*@_?a{eX+*?xmo{IGSL zN1<|7K7vgV+wglAXB-kGG=3%>aS;zFV(>)(XAd33BS8gDHd1>i`I4$HM@B6louE|l z9S<|tIVype8a)U%K+6>rhV*aiCCvU^oE*b!t)6Up6TUSlF!29uX6SH&*c! A$N&HU literal 0 HcmV?d00001 diff --git a/dogfood/files/usr/share/keyrings/nodesource.gpg b/dogfood/files/usr/share/keyrings/nodesource.gpg new file mode 100644 index 0000000000000000000000000000000000000000..4f3ec4ed793b397c15b9cba46c45cac6315dcc62 GIT binary patch literal 2206 zcmV;P2x0e`0u2OHn zGb2pT0FAJHnQ9LOen#@%F5|z&XQSYC`H_RzY$X#LGtDigk9KP_M=>ehkUPDXTu;B(V3ubAZ5m-sKU^kff*x~ zZ`Cm{)>!{y$rAt(0RRECA5L#%Wm9i;a${v6JZErcKyGhjWpi(Ja${vKV{dIfi2^tT z69EDMA_W3dnMyIxRsH;0PMkg$clS^{YTdUXw+PSWLNu=D0z2yO(O z_L)x-nN}nt%nnbK_KGzgha(e!#vOg#< zDV3pDqn*)=Wy$Atk^4+1CMYk-4;}Z1C+o<{-7M|O=%x6uUWppkB0=VIvbXoDGIP-N zq-m;2y#N%yudo`pz(4g63%S%092Zt2H^_rSC8@r4%OuDm1PL6`jbBvv&sE@N5AEzZy|9o#Den98Na`3}LhG;}Feurl9!o_En{3W5c`HWwC zvSc;MaJ?9&zEC5mh?eByw7&Ppa*vpR17SkBOr1P`{D)bx#<9JOtw?%LWi~MSqr{D{ zNjSP_F1-9@r_I*qq@)UvjrYg^>X!8+E} zMwR_59u1pS&LPPvZk6#cM&0>l7ErehWFIuqaG#&4Ss;8^akyF#TUGg3cgWiK74@o9!uIFErdKdjjITX|v%3 zUsg#~(bn4CnDl)bGku-5sX_4x@XYO}ba)la7GdHy$Y9)s2Tbpjc2)mqec%8wK)oeH zzf1hLr$%$7#PmA*m|+E-0|z^d;WJU%OJiZtIE&iROSaP6d~Rq$Tta(Ayl`-c<|&nfrwbw=OFZp*dq>L1av);N3wE+aeWA@@&(c_& zN2PxK=Q;j}EHb^6r7iLOnpdDXB(?$@3;+rV5EfOSt7unZfP>Hw0GwhUD@R{&F_wRZ1~2By zI%84XB+wDNIiGz3sLe0y#;2Uq6F0%fi_`)PxM*cuSB7^?5x?|R&E{jBF|dT)L!2P; z)Q-A^MBsW8jj{Dwp5ygBlBh3#1Opok&DJ21f%;F@xWJMBAp3s0;Zqb`x1+?$GV+=x zPki{BDcOI}xZGi?mk1f9TeS^apSix1lpg*3{%l*6d2`~ur^_x;oamqi;R^bh#Q5dw=z ze+M&hc}-v|&mj?`V^PuBYxBa+-Mi+nnag z9eQ6NssJ;!_Nnu}AX&>9GxCH~+^$})WE9M0H`$0SR}BL08A;u-$u3-jNK{Z@SnEeO03#02lO?o~>rC*DA4s+0G#EbI&sEr!W(OV literal 0 HcmV?d00001 diff --git a/dogfood/files/usr/share/keyrings/postgresql.gpg b/dogfood/files/usr/share/keyrings/postgresql.gpg new file mode 100644 index 0000000000000000000000000000000000000000..afa15cb1087de3aaad67e6d95989eb21b7501377 GIT binary patch literal 3494 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 literal 0 HcmV?d00001 diff --git a/dogfood/update-keys.sh b/dogfood/update-keys.sh new file mode 100755 index 0000000000000..9ebaf77bb5256 --- /dev/null +++ b/dogfood/update-keys.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +set -euo pipefail + +PROJECT_ROOT="$(git rev-parse --show-toplevel)" + +curl_flags=( + --silent + --show-error + --location +) + +gpg_flags=( + --dearmor + --yes +) + +pushd "$PROJECT_ROOT/dogfood/files/usr/share/keyrings" +# Upstream Docker signing key +curl "${curl_flags[@]}" "https://download.docker.com/linux/ubuntu/gpg" | + gpg "${gpg_flags[@]}" --output="docker.gpg" + +# Google Cloud signing key +curl "${curl_flags[@]}" "https://packages.cloud.google.com/apt/doc/apt-key.gpg" | + gpg "${gpg_flags[@]}" --output="google-cloud.gpg" + +# Google Linux Software repository signing key (Chrome) +curl "${curl_flags[@]}" "https://dl.google.com/linux/linux_signing_key.pub" | + gpg "${gpg_flags[@]}" --output="google-chrome.gpg" + +# Microsoft repository signing key (Edge) +curl "${curl_flags[@]}" "https://packages.microsoft.com/keys/microsoft.asc" | + gpg "${gpg_flags[@]}" --output="microsoft.gpg" + +# Upstream PostgreSQL signing key +curl "${curl_flags[@]}" "https://www.postgresql.org/media/keys/ACCC4CF8.asc" | + gpg "${gpg_flags[@]}" --output="postgresql.gpg" + +# NodeSource signing key +curl "${curl_flags[@]}" "https://deb.nodesource.com/gpgkey/nodesource.gpg.key" | + gpg "${gpg_flags[@]}" --output="nodesource.gpg" + +# Yarnpkg signing key +curl "${curl_flags[@]}" "https://dl.yarnpkg.com/debian/pubkey.gpg" | + gpg "${gpg_flags[@]}" --output="yarnpkg.gpg" + +# Ansible PPA signing key +curl "${curl_flags[@]}" "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x6125e2a8c77f2818fb7bd15b93c4a3fd7bb9c367" | + gpg "${gpg_flags[@]}" --output="ansible.gpg" + +# Neovim signing key +curl "${curl_flags[@]}" "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x9dbb0be9366964f134855e2255f96fcf8231b6dd" | + gpg "${gpg_flags[@]}" --output="neovim.gpg" + +# Hashicorp signing key +curl "${curl_flags[@]}" "https://apt.releases.hashicorp.com/gpg" | + gpg "${gpg_flags[@]}" --output="hashicorp.gpg" + +# GitHub CLI signing key +curl "${curl_flags[@]}" "https://cli.github.com/packages/githubcli-archive-keyring.gpg" | + gpg "${gpg_flags[@]}" --output="github-cli.gpg" +popd From 3d7b6a8dc02e61050e95a146234d9629e4f438b2 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Fri, 25 Aug 2023 06:03:28 +0000 Subject: [PATCH 13/13] Revert "revert deleting dogfood Docker stuff" This reverts commit 97621581670e21945c78ac46955c1862727914c7. --- dogfood/Dockerfile | 348 ------------------ dogfood/Makefile | 10 - .../files/etc/apt/apt.conf.d/80-no-recommends | 6 - dogfood/files/etc/apt/apt.conf.d/80-retries | 1 - dogfood/files/etc/apt/preferences.d/docker | 19 - .../files/etc/apt/preferences.d/github-cli | 8 - .../files/etc/apt/preferences.d/google-chrome | 16 - .../files/etc/apt/preferences.d/google-cloud | 19 - dogfood/files/etc/apt/preferences.d/hashicorp | 14 - .../etc/apt/preferences.d/microsoft-edge | 12 - .../files/etc/apt/preferences.d/nodesource | 9 - dogfood/files/etc/apt/preferences.d/ppa | 19 - dogfood/files/etc/apt/preferences.d/yarnpkg | 9 - dogfood/files/etc/apt/sources.list | 3 - .../files/etc/apt/sources.list.d/docker.list | 1 - .../etc/apt/sources.list.d/google-chrome.list | 1 - .../etc/apt/sources.list.d/google-cloud.list | 1 - .../etc/apt/sources.list.d/hashicorp.list | 1 - .../apt/sources.list.d/microsoft-edge.list | 1 - .../etc/apt/sources.list.d/nodesource.list | 1 - .../etc/apt/sources.list.d/postgresql.list | 1 - dogfood/files/etc/apt/sources.list.d/ppa.list | 2 - .../etc/apt/sources.list.d/security.list | 1 - .../files/etc/apt/sources.list.d/yarnpkg.list | 1 - dogfood/files/etc/default/google-chrome | 4 - dogfood/files/etc/default/microsoft-edge-beta | 4 - dogfood/files/etc/docker/daemon.json | 3 - dogfood/files/etc/sudoers.d/nopasswd | 1 - dogfood/files/usr/share/keyrings/ansible.gpg | Bin 1132 -> 0 bytes dogfood/files/usr/share/keyrings/docker.gpg | Bin 2760 -> 0 bytes .../files/usr/share/keyrings/github-cli.gpg | Bin 2270 -> 0 bytes .../usr/share/keyrings/google-chrome.gpg | Bin 10640 -> 0 bytes .../files/usr/share/keyrings/google-cloud.gpg | Bin 1210 -> 0 bytes .../files/usr/share/keyrings/hashicorp.gpg | Bin 2879 -> 0 bytes .../files/usr/share/keyrings/microsoft.gpg | Bin 641 -> 0 bytes dogfood/files/usr/share/keyrings/neovim.gpg | Bin 1134 -> 0 bytes .../files/usr/share/keyrings/nodesource.gpg | Bin 2206 -> 0 bytes .../files/usr/share/keyrings/postgresql.gpg | Bin 3494 -> 0 bytes dogfood/files/usr/share/keyrings/yarnpkg.gpg | Bin 10365 -> 0 bytes dogfood/update-keys.sh | 62 ---- 40 files changed, 578 deletions(-) delete mode 100644 dogfood/Dockerfile delete mode 100644 dogfood/Makefile delete mode 100644 dogfood/files/etc/apt/apt.conf.d/80-no-recommends delete mode 100644 dogfood/files/etc/apt/apt.conf.d/80-retries delete mode 100644 dogfood/files/etc/apt/preferences.d/docker delete mode 100644 dogfood/files/etc/apt/preferences.d/github-cli delete mode 100644 dogfood/files/etc/apt/preferences.d/google-chrome delete mode 100644 dogfood/files/etc/apt/preferences.d/google-cloud delete mode 100644 dogfood/files/etc/apt/preferences.d/hashicorp delete mode 100644 dogfood/files/etc/apt/preferences.d/microsoft-edge delete mode 100644 dogfood/files/etc/apt/preferences.d/nodesource delete mode 100644 dogfood/files/etc/apt/preferences.d/ppa delete mode 100644 dogfood/files/etc/apt/preferences.d/yarnpkg delete mode 100644 dogfood/files/etc/apt/sources.list delete mode 100644 dogfood/files/etc/apt/sources.list.d/docker.list delete mode 100644 dogfood/files/etc/apt/sources.list.d/google-chrome.list delete mode 100644 dogfood/files/etc/apt/sources.list.d/google-cloud.list delete mode 100644 dogfood/files/etc/apt/sources.list.d/hashicorp.list delete mode 100644 dogfood/files/etc/apt/sources.list.d/microsoft-edge.list delete mode 100644 dogfood/files/etc/apt/sources.list.d/nodesource.list delete mode 100644 dogfood/files/etc/apt/sources.list.d/postgresql.list delete mode 100644 dogfood/files/etc/apt/sources.list.d/ppa.list delete mode 100644 dogfood/files/etc/apt/sources.list.d/security.list delete mode 100644 dogfood/files/etc/apt/sources.list.d/yarnpkg.list delete mode 100644 dogfood/files/etc/default/google-chrome delete mode 100644 dogfood/files/etc/default/microsoft-edge-beta delete mode 100644 dogfood/files/etc/docker/daemon.json delete mode 100644 dogfood/files/etc/sudoers.d/nopasswd delete mode 100644 dogfood/files/usr/share/keyrings/ansible.gpg delete mode 100644 dogfood/files/usr/share/keyrings/docker.gpg delete mode 100644 dogfood/files/usr/share/keyrings/github-cli.gpg delete mode 100644 dogfood/files/usr/share/keyrings/google-chrome.gpg delete mode 100644 dogfood/files/usr/share/keyrings/google-cloud.gpg delete mode 100644 dogfood/files/usr/share/keyrings/hashicorp.gpg delete mode 100644 dogfood/files/usr/share/keyrings/microsoft.gpg delete mode 100644 dogfood/files/usr/share/keyrings/neovim.gpg delete mode 100644 dogfood/files/usr/share/keyrings/nodesource.gpg delete mode 100644 dogfood/files/usr/share/keyrings/postgresql.gpg delete mode 100644 dogfood/files/usr/share/keyrings/yarnpkg.gpg delete mode 100755 dogfood/update-keys.sh diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile deleted file mode 100644 index 8f156bd5152e8..0000000000000 --- a/dogfood/Dockerfile +++ /dev/null @@ -1,348 +0,0 @@ -FROM rust:slim AS rust-utils -# Install rust helper programs -# ENV CARGO_NET_GIT_FETCH_WITH_CLI=true -ENV CARGO_INSTALL_ROOT=/tmp/ -RUN cargo install exa bat ripgrep typos-cli watchexec-cli - -FROM ubuntu:jammy AS go - -RUN apt-get update && apt-get install --yes curl gcc -# Install Go manually, so that we can control the version -ARG GO_VERSION=1.20.7 -RUN mkdir --parents /usr/local/go - -# Boring Go is needed to build FIPS-compliant binaries. -RUN curl --silent --show-error --location \ - "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" \ - -o /usr/local/go.tar.gz - -RUN tar --extract --gzip --directory=/usr/local/go --file=/usr/local/go.tar.gz --strip-components=1 - -ENV PATH=$PATH:/usr/local/go/bin - -# Install Go utilities. -ARG GOPATH="/tmp/" -RUN mkdir --parents "$GOPATH" && \ - # moq for Go tests. - go install github.com/matryer/moq@v0.2.3 && \ - # swag for Swagger doc generation - go install github.com/swaggo/swag/cmd/swag@v1.7.4 && \ - # go-swagger tool to generate the go coder api client - go install github.com/go-swagger/go-swagger/cmd/swagger@v0.28.0 && \ - # goimports for updating imports - go install golang.org/x/tools/cmd/goimports@v0.1.7 && \ - # protoc-gen-go is needed to build sysbox from source - go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.30 && \ - # drpc support for v2 - go install storj.io/drpc/cmd/protoc-gen-go-drpc@v0.0.33 && \ - # migrate for migration support for v2 - go install github.com/golang-migrate/migrate/v4/cmd/migrate@v4.15.1 && \ - # goreleaser for compiling v2 binaries - go install github.com/goreleaser/goreleaser@v1.6.1 && \ - # Install the latest version of gopls for editors that support - # the language server protocol - go install golang.org/x/tools/gopls@latest && \ - # gotestsum makes test output more readable - go install gotest.tools/gotestsum@v1.9.0 && \ - # goveralls collects code coverage metrics from tests - # and sends to Coveralls - go install github.com/mattn/goveralls@v0.0.11 && \ - # kind for running Kubernetes-in-Docker, needed for tests - go install sigs.k8s.io/kind@v0.10.0 && \ - # helm-docs generates our Helm README based on a template and the - # charts and values files - go install github.com/norwoodj/helm-docs/cmd/helm-docs@v1.5.0 && \ - # sqlc for Go code generation - go install github.com/sqlc-dev/sqlc/cmd/sqlc@v1.20.0 && \ - # gcr-cleaner-cli used by CI to prune unused images - go install github.com/sethvargo/gcr-cleaner/cmd/gcr-cleaner-cli@v0.5.1 && \ - # ruleguard for checking custom rules, without needing to run all of - # golangci-lint. Check the go.mod in the release of golangci-lint that - # we're using for the version of go-critic that it embeds, then check - # the version of ruleguard in go-critic for that tag. - go install github.com/quasilyte/go-ruleguard/cmd/ruleguard@v0.3.13 && \ - # go-fuzz for fuzzy testing. they don't publish releases so we rely on latest. - go install github.com/dvyukov/go-fuzz/go-fuzz@latest && \ - go install github.com/dvyukov/go-fuzz/go-fuzz-build@latest && \ - # go-releaser for building 'fat binaries' that work cross-platform - go install github.com/goreleaser/goreleaser@v1.6.1 && \ - go install mvdan.cc/sh/v3/cmd/shfmt@latest && \ - # nfpm is used with `make build` to make release packages - go install github.com/goreleaser/nfpm/v2/cmd/nfpm@v2.16.0 && \ - # yq v4 is used to process yaml files in coder v2. Conflicts with - # yq v3 used in v1. - go install github.com/mikefarah/yq/v4@v4.30.6 && \ - mv /tmp/bin/yq /tmp/bin/yq4 && \ - go install github.com/golang/mock/mockgen@v1.6.0 - -FROM gcr.io/coder-dev-1/alpine:3.18 as proto -WORKDIR /tmp -RUN apk add curl unzip -RUN curl -L -o protoc.zip https://github.com/protocolbuffers/protobuf/releases/download/v23.3/protoc-23.3-linux-x86_64.zip -RUN unzip protoc.zip - -FROM ubuntu:jammy - -SHELL ["/bin/bash", "-c"] - -# Updated certificates are necessary to use the teraswitch mirror. -# This must be ran before copying in configuration since the config replaces -# the default mirror with teraswitch. -RUN apt-get update && apt-get install --yes ca-certificates - -COPY files / - -# Install packages from apt repositories -ARG DEBIAN_FRONTEND="noninteractive" - -RUN apt-get update --quiet && apt-get install --yes \ - apt-transport-https \ - apt-utils \ - bash \ - bash-completion \ - bats \ - bind9-dnsutils \ - build-essential \ - ca-certificates \ - cmake \ - crypto-policies \ - curl \ - fd-find \ - file \ - git \ - gnupg \ - graphviz \ - htop \ - httpie \ - inetutils-tools \ - iproute2 \ - iputils-ping \ - iputils-tracepath \ - jq \ - language-pack-en \ - less \ - lsb-release \ - man \ - meld \ - net-tools \ - openjdk-11-jdk-headless \ - openssh-server \ - openssl \ - libssl-dev \ - pkg-config \ - python3 \ - python3-pip \ - rsync \ - shellcheck \ - strace \ - sudo \ - tcptraceroute \ - termshark \ - traceroute \ - vim \ - wget \ - xauth \ - zip \ - ncdu \ - cargo \ - asciinema \ - zsh \ - ansible \ - neovim \ - google-cloud-sdk \ - google-cloud-sdk-datastore-emulator \ - kubectl \ - postgresql-13 \ - containerd.io \ - docker-ce \ - docker-ce-cli \ - docker-compose-plugin \ - packer \ - terraform \ - fish \ - unzip \ - zstd \ - screen \ - gettext-base && \ - # Delete package cache to avoid consuming space in layer - apt-get clean && \ - # Configure FIPS-compliant policies - update-crypto-policies --set FIPS - -# Install the docker buildx component. -RUN DOCKER_BUILDX_VERSION=$(curl -s "https://api.github.com/repos/docker/buildx/releases/latest" | grep '"tag_name":' | sed -E 's/.*"(v[^"]+)".*/\1/') && \ - mkdir -p /usr/local/lib/docker/cli-plugins && \ - curl -Lo /usr/local/lib/docker/cli-plugins/docker-buildx "https://github.com/docker/buildx/releases/download/${DOCKER_BUILDX_VERSION}/buildx-${DOCKER_BUILDX_VERSION}.linux-amd64" && \ - chmod a+x /usr/local/lib/docker/cli-plugins/docker-buildx - -# See https://github.com/cli/cli/issues/6175#issuecomment-1235984381 for proof -# the apt repository is unreliable -RUN GH_CLI_VERSION=$(curl -s "https://api.github.com/repos/cli/cli/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/') && \ - curl -L https://github.com/cli/cli/releases/download/v${GH_CLI_VERSION}/gh_${GH_CLI_VERSION}_linux_amd64.deb -o gh.deb && \ - dpkg -i gh.deb && \ - rm gh.deb - -# Install Lazygit -# See https://github.com/jesseduffield/lazygit#ubuntu -RUN LAZYGIT_VERSION=$(curl -s "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v*([^"]+)".*/\1/') && \ - curl -Lo lazygit.tar.gz "https://github.com/jesseduffield/lazygit/releases/latest/download/lazygit_${LAZYGIT_VERSION}_Linux_x86_64.tar.gz" && \ - tar xf lazygit.tar.gz -C /usr/local/bin lazygit - -# Install frontend utilities -RUN apt-get update && \ - # Node.js (from nodesource) and Yarn (from yarnpkg) - curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - &&\ - apt-get install --yes --quiet \ - nodejs yarn \ - # Install browsers for e2e testing - google-chrome-stable microsoft-edge-beta && \ - # Pre-install system dependencies that Playwright needs. npx doesn't work here - # for some reason. See https://github.com/microsoft/playwright-cli/issues/136 - npm i -g playwright@1.36.2 pnpm@^8 && playwright install-deps && \ - npm cache clean --force - -# Ensure PostgreSQL binaries are in the users $PATH. -RUN update-alternatives --install /usr/local/bin/initdb initdb /usr/lib/postgresql/13/bin/initdb 100 && \ - update-alternatives --install /usr/local/bin/postgres postgres /usr/lib/postgresql/13/bin/postgres 100 - -# Create links for injected dependencies -RUN ln --symbolic /var/tmp/coder/coder-cli/coder /usr/local/bin/coder && \ - ln --symbolic /var/tmp/coder/code-server/bin/code-server /usr/local/bin/code-server - -# Disable the PostgreSQL systemd service. -# Coder uses a custom timescale container to test the database instead. -RUN systemctl disable \ - postgresql - -# Configure systemd services for CVMs -RUN systemctl enable \ - docker \ - ssh - -# Install tools with published releases, where that is the -# preferred/recommended installation method. -ARG CLOUD_SQL_PROXY_VERSION=2.2.0 \ - DIVE_VERSION=0.10.0 \ - DOCKER_GCR_VERSION=2.1.8 \ - GOLANGCI_LINT_VERSION=1.52.2 \ - GRYPE_VERSION=0.61.1 \ - HELM_VERSION=3.12.0 \ - KUBE_LINTER_VERSION=0.6.3 \ - KUBECTX_VERSION=0.9.4 \ - STRIPE_VERSION=1.14.5 \ - TERRAGRUNT_VERSION=0.45.11 \ - TRIVY_VERSION=0.41.0 - -# cloud_sql_proxy, for connecting to cloudsql instances -# the upstream go.mod prevents this from being installed with go install -RUN curl --silent --show-error --location --output /usr/local/bin/cloud_sql_proxy "https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v${CLOUD_SQL_PROXY_VERSION}/cloud-sql-proxy.linux.amd64" && \ - chmod a=rx /usr/local/bin/cloud_sql_proxy && \ - # dive for scanning image layer utilization metrics in CI - curl --silent --show-error --location "https://github.com/wagoodman/dive/releases/download/v${DIVE_VERSION}/dive_${DIVE_VERSION}_linux_amd64.tar.gz" | \ - tar --extract --gzip --directory=/usr/local/bin --file=- dive && \ - # docker-credential-gcr is a Docker credential helper for pushing/pulling - # images from Google Container Registry and Artifact Registry - curl --silent --show-error --location "https://github.com/GoogleCloudPlatform/docker-credential-gcr/releases/download/v${DOCKER_GCR_VERSION}/docker-credential-gcr_linux_amd64-${DOCKER_GCR_VERSION}.tar.gz" | \ - tar --extract --gzip --directory=/usr/local/bin --file=- docker-credential-gcr && \ - # golangci-lint performs static code analysis for our Go code - curl --silent --show-error --location "https://github.com/golangci/golangci-lint/releases/download/v${GOLANGCI_LINT_VERSION}/golangci-lint-${GOLANGCI_LINT_VERSION}-linux-amd64.tar.gz" | \ - tar --extract --gzip --directory=/usr/local/bin --file=- --strip-components=1 "golangci-lint-${GOLANGCI_LINT_VERSION}-linux-amd64/golangci-lint" && \ - # Anchore Grype for scanning container images for security issues - curl --silent --show-error --location "https://github.com/anchore/grype/releases/download/v${GRYPE_VERSION}/grype_${GRYPE_VERSION}_linux_amd64.tar.gz" | \ - tar --extract --gzip --directory=/usr/local/bin --file=- grype && \ - # Helm is necessary for deploying Coder - curl --silent --show-error --location "https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz" | \ - tar --extract --gzip --directory=/usr/local/bin --file=- --strip-components=1 linux-amd64/helm && \ - # kube-linter for linting Kubernetes objects, including those - # that Helm generates from our charts - curl --silent --show-error --location "https://github.com/stackrox/kube-linter/releases/download/${KUBE_LINTER_VERSION}/kube-linter-linux" --output /usr/local/bin/kube-linter && \ - # kubens and kubectx for managing Kubernetes namespaces and contexts - curl --silent --show-error --location "https://github.com/ahmetb/kubectx/releases/download/v${KUBECTX_VERSION}/kubectx_v${KUBECTX_VERSION}_linux_x86_64.tar.gz" | \ - tar --extract --gzip --directory=/usr/local/bin --file=- kubectx && \ - curl --silent --show-error --location "https://github.com/ahmetb/kubectx/releases/download/v${KUBECTX_VERSION}/kubens_v${KUBECTX_VERSION}_linux_x86_64.tar.gz" | \ - tar --extract --gzip --directory=/usr/local/bin --file=- kubens && \ - # stripe for coder.com billing API - curl --silent --show-error --location "https://github.com/stripe/stripe-cli/releases/download/v${STRIPE_VERSION}/stripe_${STRIPE_VERSION}_linux_x86_64.tar.gz" | \ - tar --extract --gzip --directory=/usr/local/bin --file=- stripe && \ - # terragrunt for running Terraform and Terragrunt files - curl --silent --show-error --location --output /usr/local/bin/terragrunt "https://github.com/gruntwork-io/terragrunt/releases/download/v${TERRAGRUNT_VERSION}/terragrunt_linux_amd64" && \ - chmod a=rx /usr/local/bin/terragrunt && \ - # AquaSec Trivy for scanning container images for security issues - curl --silent --show-error --location "https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz" | \ - tar --extract --gzip --directory=/usr/local/bin --file=- trivy - -# Add Vercel globally. We can't install it in packages.json, because it -# includes Go files which make golangci-lint unhappy. -RUN yarn global add --prefix=/usr/local \ - vercel \ - typescript \ - typescript-language-server \ - prettier && \ - yarn cache clean - -# We use yq during "make deploy" to manually substitute out fields in -# our helm values.yaml file. See https://github.com/helm/helm/issues/3141 -# -# TODO: update to 4.x, we can't do this now because it included breaking -# changes (yq w doesn't work anymore) -# RUN curl --silent --show-error --location "https://github.com/mikefarah/yq/releases/download/v4.9.0/yq_linux_amd64.tar.gz" | \ -# tar --extract --gzip --directory=/usr/local/bin --file=- ./yq_linux_amd64 && \ -# mv /usr/local/bin/yq_linux_amd64 /usr/local/bin/yq - -RUN curl --silent --show-error --location --output /usr/local/bin/yq "https://github.com/mikefarah/yq/releases/download/3.3.0/yq_linux_amd64" && \ - chmod a=rx /usr/local/bin/yq - -# Install GoLand. -RUN mkdir --parents /usr/local/goland && \ - curl --silent --show-error --location "https://download.jetbrains.com/go/goland-2021.2.tar.gz" | \ - tar --extract --gzip --directory=/usr/local/goland --file=- --strip-components=1 && \ - ln --symbolic /usr/local/goland/bin/goland.sh /usr/local/bin/goland - -# Install Antlrv4, needed to generate paramlang lexer/parser -RUN curl --silent --show-error --location --output /usr/local/lib/antlr-4.9.2-complete.jar "https://www.antlr.org/download/antlr-4.9.2-complete.jar" -ENV CLASSPATH="/usr/local/lib/antlr-4.9.2-complete.jar:${PATH}" - -# Add coder user and allow use of docker/sudo -RUN useradd coder \ - --create-home \ - --shell=/bin/bash \ - --groups=docker \ - --uid=1000 \ - --user-group - -# Adjust OpenSSH config -RUN echo "PermitUserEnvironment yes" >>/etc/ssh/sshd_config && \ - echo "X11Forwarding yes" >>/etc/ssh/sshd_config && \ - echo "X11UseLocalhost no" >>/etc/ssh/sshd_config - -# We avoid copying the extracted directory since COPY slows to minutes when there -# are a lot of small files. -COPY --from=go /usr/local/go.tar.gz /usr/local/go.tar.gz -RUN mkdir /usr/local/go && \ - tar --extract --gzip --directory=/usr/local/go --file=/usr/local/go.tar.gz --strip-components=1 - -ENV PATH=$PATH:/usr/local/go/bin - -RUN update-alternatives --install /usr/local/bin/gofmt gofmt /usr/local/go/bin/gofmt 100 - -COPY --from=go /tmp/bin /usr/local/bin -COPY --from=rust-utils /tmp/bin /usr/local/bin -COPY --from=proto /tmp/bin /usr/local/bin -COPY --from=proto /tmp/include /usr/local/bin/include - -USER coder - -# Ensure go bins are in the 'coder' user's path. Note that no go bins are -# installed in this docker file, as they'd be mounted over by the persistent -# home volume. -ENV PATH="/home/coder/go/bin:${PATH}" - -# This setting prevents Go from using the public checksum database for -# our module path prefixes. It is required because these are in private -# repositories that require authentication. -# -# For details, see: https://golang.org/ref/mod#private-modules -ENV GOPRIVATE="coder.com,cdr.dev,go.coder.com,github.com/cdr,github.com/coder" - -# Increase memory allocation to NodeJS -ENV NODE_OPTIONS="--max-old-space-size=8192" diff --git a/dogfood/Makefile b/dogfood/Makefile deleted file mode 100644 index 061530f50dd45..0000000000000 --- a/dogfood/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -.PHONY: docker-build docker-push - -branch=$(shell git rev-parse --abbrev-ref HEAD) -build_tag=codercom/oss-dogfood:${branch} - -build: - DOCKER_BUILDKIT=1 docker build . -t ${build_tag} - -push: build - docker push ${build_tag} diff --git a/dogfood/files/etc/apt/apt.conf.d/80-no-recommends b/dogfood/files/etc/apt/apt.conf.d/80-no-recommends deleted file mode 100644 index 8cb79c96386c4..0000000000000 --- a/dogfood/files/etc/apt/apt.conf.d/80-no-recommends +++ /dev/null @@ -1,6 +0,0 @@ -// Do not install recommended packages by default -APT::Install-Recommends "0"; - -// Do not install suggested packages by default (this is already -// the Ubuntu default) -APT::Install-Suggests "0"; diff --git a/dogfood/files/etc/apt/apt.conf.d/80-retries b/dogfood/files/etc/apt/apt.conf.d/80-retries deleted file mode 100644 index d7ee5185258ec..0000000000000 --- a/dogfood/files/etc/apt/apt.conf.d/80-retries +++ /dev/null @@ -1 +0,0 @@ -APT::Acquire::Retries "3"; diff --git a/dogfood/files/etc/apt/preferences.d/docker b/dogfood/files/etc/apt/preferences.d/docker deleted file mode 100644 index a92c0abb03d7c..0000000000000 --- a/dogfood/files/etc/apt/preferences.d/docker +++ /dev/null @@ -1,19 +0,0 @@ -# Ignore all packages from this repository by default -Package: * -Pin: origin download.docker.com -Pin-Priority: 1 - -# Docker Community Edition -Package: docker-ce -Pin: origin download.docker.com -Pin-Priority: 500 - -# Docker command-line tool -Package: docker-ce-cli -Pin: origin download.docker.com -Pin-Priority: 500 - -# containerd runtime -Package: containerd.io -Pin: origin download.docker.com -Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/github-cli b/dogfood/files/etc/apt/preferences.d/github-cli deleted file mode 100644 index d2dce9f5f3097..0000000000000 --- a/dogfood/files/etc/apt/preferences.d/github-cli +++ /dev/null @@ -1,8 +0,0 @@ -# Ignore all packages from this repository by default -Package: * -Pin: origin cli.github.com -Pin-Priority: 1 - -Package: gh -Pin: origin cli.github.com -Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/google-chrome b/dogfood/files/etc/apt/preferences.d/google-chrome deleted file mode 100644 index 4551ec390ff20..0000000000000 --- a/dogfood/files/etc/apt/preferences.d/google-chrome +++ /dev/null @@ -1,16 +0,0 @@ -# Ignore all packages from this repository by default -Package: * -Pin: origin dl.google.com -Pin-Priority: 1 - -Package: google-chrome-stable -Pin: origin dl.google.com -Pin-Priority: 500 - -Package: google-chrome-beta -Pin: origin dl.google.com -Pin-Priority: 500 - -Package: google-chrome-unstable -Pin: origin dl.google.com -Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/google-cloud b/dogfood/files/etc/apt/preferences.d/google-cloud deleted file mode 100644 index 637b0e9bb3c51..0000000000000 --- a/dogfood/files/etc/apt/preferences.d/google-cloud +++ /dev/null @@ -1,19 +0,0 @@ -# Ignore all packages from this repository by default -Package: * -Pin: origin packages.cloud.google.com -Pin-Priority: 1 - -# Google Cloud SDK for gcloud and gsutil CLI tools -Package: google-cloud-sdk -Pin: origin packages.cloud.google.com -Pin-Priority: 500 - -# Datastore emulator for working with the licensor -Package: google-cloud-sdk-datastore-emulator -Pin: origin packages.cloud.google.com -Pin-Priority: 500 - -# Kubectl for working with Kubernetes (GKE) -Package: kubectl -Pin: origin packages.cloud.google.com -Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/hashicorp b/dogfood/files/etc/apt/preferences.d/hashicorp deleted file mode 100644 index 4323f331cc722..0000000000000 --- a/dogfood/files/etc/apt/preferences.d/hashicorp +++ /dev/null @@ -1,14 +0,0 @@ -# Ignore all packages from this repository by default -Package: * -Pin: origin apt.releases.hashicorp.com -Pin-Priority: 1 - -# Packer for creating virtual machine disk images -Package: packer -Pin: origin apt.releases.hashicorp.com -Pin-Priority: 500 - -# Terraform for managing infrastructure -Package: terraform -Pin: origin apt.releases.hashicorp.com -Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/microsoft-edge b/dogfood/files/etc/apt/preferences.d/microsoft-edge deleted file mode 100644 index 2441961adac38..0000000000000 --- a/dogfood/files/etc/apt/preferences.d/microsoft-edge +++ /dev/null @@ -1,12 +0,0 @@ -# Ignore all packages from this repository by default -Package: * -Pin: origin packages.microsoft.com -Pin-Priority: 1 - -Package: microsoft-edge-beta -Pin: origin packages.microsoft.com -Pin-Priority: 500 - -Package: microsoft-edge-dev -Pin: origin packages.microsoft.com -Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/nodesource b/dogfood/files/etc/apt/preferences.d/nodesource deleted file mode 100644 index de55d5553411e..0000000000000 --- a/dogfood/files/etc/apt/preferences.d/nodesource +++ /dev/null @@ -1,9 +0,0 @@ -# Ignore all packages from this repository by default -Package: * -Pin: origin deb.nodesource.com -Pin-Priority: 1 - -# Node.js for building the frontend -Package: nodejs -Pin: origin deb.nodesource.com -Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/ppa b/dogfood/files/etc/apt/preferences.d/ppa deleted file mode 100644 index 1dc9da8f9fffc..0000000000000 --- a/dogfood/files/etc/apt/preferences.d/ppa +++ /dev/null @@ -1,19 +0,0 @@ -# Ignore all packages from this repository by default -Package: * -Pin: origin ppa.launchpad.net -Pin-Priority: 1 - -# Ansible -Package: ansible-base -Pin: origin ppa.launchpad.net -Pin-Priority: 500 - -# Neovim -Package: neovim -Pin: origin ppa.launchpad.net -Pin-Priority: 500 - -# Neovim Runtime -Package: neovim-runtime -Pin: origin ppa.launchpad.net -Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/preferences.d/yarnpkg b/dogfood/files/etc/apt/preferences.d/yarnpkg deleted file mode 100644 index 7237fcad5c356..0000000000000 --- a/dogfood/files/etc/apt/preferences.d/yarnpkg +++ /dev/null @@ -1,9 +0,0 @@ -# Ignore all packages from this repository by default -Package: * -Pin: origin dl.yarnpkg.com -Pin-Priority: 1 - -# Yarn for managing Node.js packages -Package: yarn -Pin: origin dl.yarnpkg.com -Pin-Priority: 500 diff --git a/dogfood/files/etc/apt/sources.list b/dogfood/files/etc/apt/sources.list deleted file mode 100644 index 745bcefcf2b0c..0000000000000 --- a/dogfood/files/etc/apt/sources.list +++ /dev/null @@ -1,3 +0,0 @@ -deb https://mirror.pit.teraswitch.com/ubuntu/ jammy main restricted universe -deb https://mirror.pit.teraswitch.com/ubuntu/ jammy-updates main restricted universe -deb https://mirror.pit.teraswitch.com/ubuntu/ jammy-backports main restricted universe diff --git a/dogfood/files/etc/apt/sources.list.d/docker.list b/dogfood/files/etc/apt/sources.list.d/docker.list deleted file mode 100644 index f00cada1ad16e..0000000000000 --- a/dogfood/files/etc/apt/sources.list.d/docker.list +++ /dev/null @@ -1 +0,0 @@ -deb [signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu jammy stable diff --git a/dogfood/files/etc/apt/sources.list.d/google-chrome.list b/dogfood/files/etc/apt/sources.list.d/google-chrome.list deleted file mode 100644 index 8dd71926f26df..0000000000000 --- a/dogfood/files/etc/apt/sources.list.d/google-chrome.list +++ /dev/null @@ -1 +0,0 @@ -deb [signed-by=/usr/share/keyrings/google-chrome.gpg] https://dl.google.com/linux/chrome/deb/ stable main diff --git a/dogfood/files/etc/apt/sources.list.d/google-cloud.list b/dogfood/files/etc/apt/sources.list.d/google-cloud.list deleted file mode 100644 index 24df98effea28..0000000000000 --- a/dogfood/files/etc/apt/sources.list.d/google-cloud.list +++ /dev/null @@ -1 +0,0 @@ -deb [signed-by=/usr/share/keyrings/google-cloud.gpg] https://packages.cloud.google.com/apt cloud-sdk main diff --git a/dogfood/files/etc/apt/sources.list.d/hashicorp.list b/dogfood/files/etc/apt/sources.list.d/hashicorp.list deleted file mode 100644 index 6e60053905ec7..0000000000000 --- a/dogfood/files/etc/apt/sources.list.d/hashicorp.list +++ /dev/null @@ -1 +0,0 @@ -deb [signed-by=/usr/share/keyrings/hashicorp.gpg] https://apt.releases.hashicorp.com jammy main diff --git a/dogfood/files/etc/apt/sources.list.d/microsoft-edge.list b/dogfood/files/etc/apt/sources.list.d/microsoft-edge.list deleted file mode 100644 index f0c036f79a5c5..0000000000000 --- a/dogfood/files/etc/apt/sources.list.d/microsoft-edge.list +++ /dev/null @@ -1 +0,0 @@ -deb [signed-by=/usr/share/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/edge stable main diff --git a/dogfood/files/etc/apt/sources.list.d/nodesource.list b/dogfood/files/etc/apt/sources.list.d/nodesource.list deleted file mode 100644 index a328c2c3c47dc..0000000000000 --- a/dogfood/files/etc/apt/sources.list.d/nodesource.list +++ /dev/null @@ -1 +0,0 @@ -deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_16.x jammy main diff --git a/dogfood/files/etc/apt/sources.list.d/postgresql.list b/dogfood/files/etc/apt/sources.list.d/postgresql.list deleted file mode 100644 index 10262f3e64a10..0000000000000 --- a/dogfood/files/etc/apt/sources.list.d/postgresql.list +++ /dev/null @@ -1 +0,0 @@ -deb [signed-by=/usr/share/keyrings/postgresql.gpg] https://apt.postgresql.org/pub/repos/apt jammy-pgdg main diff --git a/dogfood/files/etc/apt/sources.list.d/ppa.list b/dogfood/files/etc/apt/sources.list.d/ppa.list deleted file mode 100644 index e817c20915cb1..0000000000000 --- a/dogfood/files/etc/apt/sources.list.d/ppa.list +++ /dev/null @@ -1,2 +0,0 @@ -deb [signed-by=/usr/share/keyrings/ansible.gpg] https://ppa.launchpadcontent.net/ansible/ansible/ubuntu focal main -deb [signed-by=/usr/share/keyrings/neovim.gpg] https://ppa.launchpadcontent.net/neovim-ppa/stable/ubuntu focal main diff --git a/dogfood/files/etc/apt/sources.list.d/security.list b/dogfood/files/etc/apt/sources.list.d/security.list deleted file mode 100644 index 1f3dae8d09b19..0000000000000 --- a/dogfood/files/etc/apt/sources.list.d/security.list +++ /dev/null @@ -1 +0,0 @@ -deb http://security.ubuntu.com/ubuntu/ jammy-security main restricted universe diff --git a/dogfood/files/etc/apt/sources.list.d/yarnpkg.list b/dogfood/files/etc/apt/sources.list.d/yarnpkg.list deleted file mode 100644 index ada8a06f7b9b2..0000000000000 --- a/dogfood/files/etc/apt/sources.list.d/yarnpkg.list +++ /dev/null @@ -1 +0,0 @@ -deb [signed-by=/usr/share/keyrings/yarnpkg.gpg] https://dl.yarnpkg.com/debian/ stable main diff --git a/dogfood/files/etc/default/google-chrome b/dogfood/files/etc/default/google-chrome deleted file mode 100644 index 8620a6054380a..0000000000000 --- a/dogfood/files/etc/default/google-chrome +++ /dev/null @@ -1,4 +0,0 @@ -# These settings are required to prevent the postinst script -# from modifying /etc/apt/sources.list.d -repo_add_once="false" -repo_reenable_on_distupgrade="false" diff --git a/dogfood/files/etc/default/microsoft-edge-beta b/dogfood/files/etc/default/microsoft-edge-beta deleted file mode 100644 index 8620a6054380a..0000000000000 --- a/dogfood/files/etc/default/microsoft-edge-beta +++ /dev/null @@ -1,4 +0,0 @@ -# These settings are required to prevent the postinst script -# from modifying /etc/apt/sources.list.d -repo_add_once="false" -repo_reenable_on_distupgrade="false" diff --git a/dogfood/files/etc/docker/daemon.json b/dogfood/files/etc/docker/daemon.json deleted file mode 100644 index 8e19eeeec15b8..0000000000000 --- a/dogfood/files/etc/docker/daemon.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "registry-mirrors": ["https://mirror.gcr.io"] -} diff --git a/dogfood/files/etc/sudoers.d/nopasswd b/dogfood/files/etc/sudoers.d/nopasswd deleted file mode 100644 index 3283f4455630c..0000000000000 --- a/dogfood/files/etc/sudoers.d/nopasswd +++ /dev/null @@ -1 +0,0 @@ -coder ALL=(ALL) NOPASSWD:ALL diff --git a/dogfood/files/usr/share/keyrings/ansible.gpg b/dogfood/files/usr/share/keyrings/ansible.gpg deleted file mode 100644 index 1731dd2b2fbd7ce251ad1b2a53f7df432f40ba60..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1132 zcmV-y1e5#5!A%5Hmu)Zs5CF<8#y2sBavX?)67L*C?G(=zXq7e@f6Q6auif(;)LZod zJu=nD{xl;si4m1N>|mHxbs=?y#0s%cDFcoXWGuiOPPcBqgGtD(O&)chTnV3O_vTKp zpxjBtjm2l2l)Co$f!&#ZUZx+mr|if+XiX)imRGOaN{wFzF5qf*MMMWR-!r_9)GT8n z9-skmj@@r=PeO_JMTAEoMON^=mLX&{p9PrVXI@k~>Eol0;1Wto(EAo0j!ob9JLZv$ zz{J9ga|)i0iWfLtD7Lfx2pcwfa@C_G1MjY`Lz6(awYWneCUowKp!;(c|LRENDJuV@}J^R10+K>bBPj0 zCcgwPd7G4u#uSnVISiLz>kj2k1P55=&JfyHmd(KqdSL^A$;r(RK;Xi~)S07(S1`Hx zluz`k@CoV<@SfH`dGGH;tTOf>%sFH)iWJCW^83^D=M##Vb)#E2kuO`HOHZMJPPY`) z#rAzJVN>~#YhaCw6qRIee66;(wewmmFwLqfI#xM7Uyj4+Unp~Z9?dnFy^Ep&k9z1@*%FAsQAQg_q^ zZA|2Ax}@E=%BDtciOPD+c(7l!ho;1z9^v?+=mW{bPK7@|z`h3!+#5lH>mC;e zAZw{ca%yxWx*r-8+j=+B_0_#@aD^lrQGYcRci@}xrY_B1bATdXsNhK*{R`_5@Snvl z%@^X(#j_I0E(`LpP@0t-%adrgYf0nv{mkf^m#uEZhfVP0mH+ABM$$9YYGhc7uU_zb zLfwi01ixZuFJvRqgLiooRMNo7-bQbSnxUT8je#Ug{poZ{T)y9ck!Lmb=J$T22%i1(LzY!TWhePHBrdo)WGPY3)h z7C#hPORz)L!-36Ks;a^piJc|8(PTGnSad{%|NB2-0#?2=Ng~I(^p!6?WEWF|1MY|_ yf9W@2In1 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 diff --git a/dogfood/files/usr/share/keyrings/google-chrome.gpg b/dogfood/files/usr/share/keyrings/google-chrome.gpg deleted file mode 100644 index cee005a7386d9c20b1500ed18f58e98d5ecb7468..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10640 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 NoHjgY=A3`m{~vJw|Kb1u diff --git a/dogfood/files/usr/share/keyrings/google-cloud.gpg b/dogfood/files/usr/share/keyrings/google-cloud.gpg deleted file mode 100644 index 0f478144f1491ce0e6668faf181eb8a7f24a208a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1210 zcmV;r1V#JCz)b{Vh_%!K2mscYq|IbT7J+=b+*`^Oj$cN)IJ9G0;1{?}mAAo~T({7p z@JRBJPSW&4=qGU6)ec&2A)J#VmCA#C z|M1{S^3O7Tn&fI1N7}adYPQ9-dtC8TNI+&0-YS5c37a=4rb<3Z*5_8X=5N$X=iR}Zf77%WqBYd zV{C7AWG!-GaCCKYWi4}QXKrb3XDw@Gc`Y(9GBPbNGc7PTEigD=Ffm^+F)na*VkyGF zVgwTb2mlrZ0%C}@)Cmx^J;)6c?e7Hw8v_Cv0RRBOs0aXjKodwH-O$)Q+G-l#k-nP6 z-g(UI5z^V~isDhA@#r?{D>{&`^`(q5^Z*Feq{hq1#6f&HM)QRxBLNe^^t$sHNzEqccHSo% zWsaw#U7E)!v2s_x`5>lsuP6)$+R`k5+AN^`i?ZAY*DKFab29GU>|zfq z_$t}Yd{Gm@ThG7^`GAXx1RftieU>Qkk}w6Y>tP2%D?0A$y8~GIYu!JmKzju)uj)x? zh{SvDEbx#-6}|z)m%#-4gluH7ZY~ZyLT^FOIb521d65cueP!h;<8zGj#n0vikf07;k#0EH9e{n2CZR@D7O*RDY%Wt_zHoYaA-|F+zb ztzM99RzL(CpW>Dy20yYatT)@uKm3)htg12E?8K{BU0nB_L~;T~=yeu1bkd7jL+l0@ zc^L1E1ukma{Wm(HKA4kQvSzePTx1NxT5T!@PC$-o`; z(ghh8M)_;m7^ArH11OC^u!uzAl7Me+BshQcv zn$%;AzR1N#hH7P2I|9&cO8(!2FwNJAb;A68tNAPs6q8G($>rU`APVqOkg_aD`xbA{ YvDCB4XX2J{8xPZ_^SyA%2cipL&5QI%SpWb4 diff --git a/dogfood/files/usr/share/keyrings/hashicorp.gpg b/dogfood/files/usr/share/keyrings/hashicorp.gpg deleted file mode 100644 index 674dd40c4219e7f397ea58978a945ccf952b79ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2879 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 F;BR8aVf_FA diff --git a/dogfood/files/usr/share/keyrings/microsoft.gpg b/dogfood/files/usr/share/keyrings/microsoft.gpg deleted file mode 100644 index 0cffae08d061d6ae8959b4442dd2dbce26c340e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 641 zcmV-{0)G9O0SyFJF<6WN2mrt;hGAw>aTw8-&ZU0T;kCvj9-@p2hRX&3tKIp#mk44K zWSkQ%c4{HQA}s#tsn;1=(LHS^JIEF`F{wkR(&D>9o|7yP=~Y+NKK3;C`4axI=rYyq zrB<*k)BskBDEsDx5Yd^pAvz|*XxLN^Rs1tKcJz?E$yQpt@e`p4a|{c zMCET7wg8i5k#M`dMmXStEMdYRelqXC@i+Karv74@Qsaue67_2{MmJAUtPq zXLDs^b#iHRc|dJxV{&hEZ)S8ZV{dIfi2*eP69EDM9|ZzdF<6WO8v_Ol2?z%R0t6KT z2m=Ea0s#UZ0Rk6*0162Z>pqmNz7i?V8k-0IeXlDmy&evAAJ<zH{duFkO6N3 z&j)GB_6-&>FO*4L(_oK+UEBCNPtqruWb}jtrH<)Fo&NESBL93CCK@(!cM{sFL# zl3lGc*OY}TPJY89Y`5yhtDjdGdR`sF=-obeZ6|&)Q?JB*^tR`Hs`bI;7%7s23ub3m z2fb~VjF|gS`dseajhzmSVAqkLq?Lzd-||b!CPpP=s@8rTvf6|&1HsVQ^$#~j*4_B z^wo#Yk$Y085z>xnXPh*YyXCM?X!Pz34&qQJWF>^y#mQ?Jy36e=iZ;jd+pzLw&Z~qp z9J+_wM!!;)U9TJ>|{QL461&b!QjK$m6TSoI*Z?BZZUGed_%I zq@w4C+YUK7V*G66P1FMCB=1(Q0v{fk--rSn_+rv#2P+VoJ}C|S6~o~oM@taQ>Mq^X z*FGXUmgmLfb&~)Q0RREbAxvR)ZewV0VPqgsP(dJOZ*m|`Wp8$AZ6HukK_FCRVQs>} zcmxvx0stZf0#u33qXHWP1`7!Y2Ll2I6$k|8!UY)ML z?f{O&>KSG%w!M&okwu6`ShMAUxoz)SabFLueiM$KoUDI zx!sM%wVVU={@k`?+zS~>77|toi>_NThL3?qSo_W5_Z>u62g!RHUcPk*2{p^0b>g{i ziDBYyHCIbR6O^dmyn%PY9&_=gKp zB2Dn)pL>}Y{`@YqQu8<*4#ucVWl@T&o5F~wef_KAIEV1sIIj~eCi0EgcN%>#{rn3}1Kqr1_6^$8%9?VPE|Luu{wV46z1K0qY z)(wi}yw|tNeAvYIe{9Y+h3YF|_DbZK{aU{)%!HvAI@XQ2l*@_?a{eX+*?xmo{IGSL zN1<|7K7vgV+wglAXB-kGG=3%>aS;zFV(>)(XAd33BS8gDHd1>i`I4$HM@B6louE|l z9S<|tIVype8a)U%K+6>rhV*aiCCvU^oE*b!t)6Up6TUSlF!29uX6SH&*c! A$N&HU diff --git a/dogfood/files/usr/share/keyrings/nodesource.gpg b/dogfood/files/usr/share/keyrings/nodesource.gpg deleted file mode 100644 index 4f3ec4ed793b397c15b9cba46c45cac6315dcc62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2206 zcmV;P2x0e`0u2OHn zGb2pT0FAJHnQ9LOen#@%F5|z&XQSYC`H_RzY$X#LGtDigk9KP_M=>ehkUPDXTu;B(V3ubAZ5m-sKU^kff*x~ zZ`Cm{)>!{y$rAt(0RRECA5L#%Wm9i;a${v6JZErcKyGhjWpi(Ja${vKV{dIfi2^tT z69EDMA_W3dnMyIxRsH;0PMkg$clS^{YTdUXw+PSWLNu=D0z2yO(O z_L)x-nN}nt%nnbK_KGzgha(e!#vOg#< zDV3pDqn*)=Wy$Atk^4+1CMYk-4;}Z1C+o<{-7M|O=%x6uUWppkB0=VIvbXoDGIP-N zq-m;2y#N%yudo`pz(4g63%S%092Zt2H^_rSC8@r4%OuDm1PL6`jbBvv&sE@N5AEzZy|9o#Den98Na`3}LhG;}Feurl9!o_En{3W5c`HWwC zvSc;MaJ?9&zEC5mh?eByw7&Ppa*vpR17SkBOr1P`{D)bx#<9JOtw?%LWi~MSqr{D{ zNjSP_F1-9@r_I*qq@)UvjrYg^>X!8+E} zMwR_59u1pS&LPPvZk6#cM&0>l7ErehWFIuqaG#&4Ss;8^akyF#TUGg3cgWiK74@o9!uIFErdKdjjITX|v%3 zUsg#~(bn4CnDl)bGku-5sX_4x@XYO}ba)la7GdHy$Y9)s2Tbpjc2)mqec%8wK)oeH zzf1hLr$%$7#PmA*m|+E-0|z^d;WJU%OJiZtIE&iROSaP6d~Rq$Tta(Ayl`-c<|&nfrwbw=OFZp*dq>L1av);N3wE+aeWA@@&(c_& zN2PxK=Q;j}EHb^6r7iLOnpdDXB(?$@3;+rV5EfOSt7unZfP>Hw0GwhUD@R{&F_wRZ1~2By zI%84XB+wDNIiGz3sLe0y#;2Uq6F0%fi_`)PxM*cuSB7^?5x?|R&E{jBF|dT)L!2P; z)Q-A^MBsW8jj{Dwp5ygBlBh3#1Opok&DJ21f%;F@xWJMBAp3s0;Zqb`x1+?$GV+=x zPki{BDcOI}xZGi?mk1f9TeS^apSix1lpg*3{%l*6d2`~ur^_x;oamqi;R^bh#Q5dw=z ze+M&hc}-v|&mj?`V^PuBYxBa+-Mi+nnag z9eQ6NssJ;!_Nnu}AX&>9GxCH~+^$})WE9M0H`$0SR}BL08A;u-$u3-jNK{Z@SnEeO03#02lO?o~>rC*DA4s+0G#EbI&sEr!W(OV diff --git a/dogfood/files/usr/share/keyrings/postgresql.gpg b/dogfood/files/usr/share/keyrings/postgresql.gpg deleted file mode 100644 index afa15cb1087de3aaad67e6d95989eb21b7501377..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3494 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 diff --git a/dogfood/update-keys.sh b/dogfood/update-keys.sh deleted file mode 100755 index 9ebaf77bb5256..0000000000000 --- a/dogfood/update-keys.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -PROJECT_ROOT="$(git rev-parse --show-toplevel)" - -curl_flags=( - --silent - --show-error - --location -) - -gpg_flags=( - --dearmor - --yes -) - -pushd "$PROJECT_ROOT/dogfood/files/usr/share/keyrings" -# Upstream Docker signing key -curl "${curl_flags[@]}" "https://download.docker.com/linux/ubuntu/gpg" | - gpg "${gpg_flags[@]}" --output="docker.gpg" - -# Google Cloud signing key -curl "${curl_flags[@]}" "https://packages.cloud.google.com/apt/doc/apt-key.gpg" | - gpg "${gpg_flags[@]}" --output="google-cloud.gpg" - -# Google Linux Software repository signing key (Chrome) -curl "${curl_flags[@]}" "https://dl.google.com/linux/linux_signing_key.pub" | - gpg "${gpg_flags[@]}" --output="google-chrome.gpg" - -# Microsoft repository signing key (Edge) -curl "${curl_flags[@]}" "https://packages.microsoft.com/keys/microsoft.asc" | - gpg "${gpg_flags[@]}" --output="microsoft.gpg" - -# Upstream PostgreSQL signing key -curl "${curl_flags[@]}" "https://www.postgresql.org/media/keys/ACCC4CF8.asc" | - gpg "${gpg_flags[@]}" --output="postgresql.gpg" - -# NodeSource signing key -curl "${curl_flags[@]}" "https://deb.nodesource.com/gpgkey/nodesource.gpg.key" | - gpg "${gpg_flags[@]}" --output="nodesource.gpg" - -# Yarnpkg signing key -curl "${curl_flags[@]}" "https://dl.yarnpkg.com/debian/pubkey.gpg" | - gpg "${gpg_flags[@]}" --output="yarnpkg.gpg" - -# Ansible PPA signing key -curl "${curl_flags[@]}" "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x6125e2a8c77f2818fb7bd15b93c4a3fd7bb9c367" | - gpg "${gpg_flags[@]}" --output="ansible.gpg" - -# Neovim signing key -curl "${curl_flags[@]}" "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x9dbb0be9366964f134855e2255f96fcf8231b6dd" | - gpg "${gpg_flags[@]}" --output="neovim.gpg" - -# Hashicorp signing key -curl "${curl_flags[@]}" "https://apt.releases.hashicorp.com/gpg" | - gpg "${gpg_flags[@]}" --output="hashicorp.gpg" - -# GitHub CLI signing key -curl "${curl_flags[@]}" "https://cli.github.com/packages/githubcli-archive-keyring.gpg" | - gpg "${gpg_flags[@]}" --output="github-cli.gpg" -popd