diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2692f814..6cf81a20 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,13 +16,12 @@ This repo uses [Conventional Commits](https://www.conventionalcommits.org/en/v1. **To Edit Protobuffers** ```sh apt install -y protobuf-compiler -go install \ - github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest \ - github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest -go install github.com/grpc-ecosystem/protoc-gen-grpc-gateway-ts@latest -go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest go install github.com/bufbuild/buf/cmd/buf@v1.27.2 +go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest +go install google.golang.org/protobuf/cmd/protoc-gen-go@latest +go install connectrpc.com/connect/cmd/protoc-gen-connect-go@latest +npm install -g @bufbuild/protoc-gen-es @connectrpc/protoc-gen-connect-es ``` ## Building diff --git a/backrest.go b/backrest.go index 311fb532..6fc0692c 100644 --- a/backrest.go +++ b/backrest.go @@ -13,6 +13,7 @@ import ( "syscall" rice "github.com/GeertJohan/go.rice" + "github.com/garethgeorge/backrest/gen/go/v1/v1connect" "github.com/garethgeorge/backrest/internal/api" "github.com/garethgeorge/backrest/internal/config" "github.com/garethgeorge/backrest/internal/oplog" @@ -22,16 +23,13 @@ import ( "go.etcd.io/bbolt" "go.uber.org/zap" "go.uber.org/zap/zapcore" -) - -var ( - installOnly = flag.Bool("install-deps", false, "Install backrest and exit") + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" ) func main() { flag.Parse() - ctx := context.Background() - ctx, cancel := context.WithCancel(ctx) + ctx, cancel := context.WithCancel(context.Background()) go onterm(cancel) resticPath, err := resticinstaller.FindOrInstallResticBinary() @@ -39,12 +37,8 @@ func main() { zap.S().Fatalf("Error finding or installing restic: %v", err) } - if *installOnly { - return - } - + // Load the configuration configStore := createConfigProvider() - cfg, err := configStore.Get() if err != nil { zap.S().Fatalf("Error loading config: %v", err) @@ -52,16 +46,7 @@ func main() { var wg sync.WaitGroup - // Configure the HTTP mux - mux := http.NewServeMux() - - if box, err := rice.FindBox("webui/dist"); err == nil { - mux.Handle("/", http.FileServer(box.HTTPBox())) - } else { - zap.S().Warnf("Error loading static assets, not serving UI: %v", err) - } - - // Create and serve API server + // Create / load the operation log oplogFile := path.Join(config.DataDir(), "oplog.boltdb") oplog, err := oplog.NewOpLog(oplogFile) if err != nil { @@ -73,51 +58,50 @@ func main() { } defer oplog.Close() + // Create orchestrator and start task loop. orchestrator, err := orchestrator.NewOrchestrator(resticPath, cfg, oplog) if err != nil { zap.S().Fatalf("Error creating orchestrator: %v", err) } - // Start orchestration loop. Only exits when ctx is cancelled. - go orchestrator.Run(ctx) + wg.Add(1) + go func() { + orchestrator.Run(ctx) + wg.Done() + }() + // Create and serve the HTTP gateway apiServer := api.NewServer( configStore, orchestrator, // TODO: eliminate default config oplog, ) - // Serve the API - wg.Add(1) - go func() { - defer wg.Done() - err := api.ServeAPI(ctx, apiServer, mux) - if err != nil { - zap.S().Fatal("Error serving API", zap.Error(err)) - } - cancel() // cancel the context when the API server exits (e.g. on fatal error) - }() + mux := http.NewServeMux() + + if box, err := rice.FindBox("webui/dist"); err == nil { + mux.Handle("/", http.FileServer(box.HTTPBox())) + } else { + zap.S().Warnf("Error loading static assets, not serving UI: %v", err) + } + + mux.Handle(v1connect.NewBackrestHandler(apiServer)) // Serve the HTTP gateway server := &http.Server{ Addr: config.BindAddress(), - Handler: mux, + Handler: h2c.NewHandler(mux, &http2.Server{}), // h2c is HTTP/2 without TLS for grpc-connect support. } - wg.Add(1) + zap.S().Infof("Starting web server %v", server.Addr) go func() { - defer wg.Done() - zap.S().Infof("Starting web server %v", server.Addr) - go func() { - <-ctx.Done() - server.Shutdown(context.Background()) - }() - if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { - zap.L().Error("Error starting server", zap.Error(err)) - } - zap.L().Info("HTTP gateway shutdown") - cancel() // cancel the context when the HTTP server exits (e.g. on fatal error) + <-ctx.Done() + server.Shutdown(context.Background()) }() + if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { + zap.L().Error("Error starting server", zap.Error(err)) + } + zap.L().Info("HTTP gateway shutdown") wg.Wait() } diff --git a/gen/go/google/api/annotations.pb.go b/gen/go/google/api/annotations.pb.go index d67c95ea..5c925002 100644 --- a/gen/go/google/api/annotations.pb.go +++ b/gen/go/google/api/annotations.pb.go @@ -14,7 +14,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc (unknown) // source: google/api/annotations.proto diff --git a/gen/go/google/api/http.pb.go b/gen/go/google/api/http.pb.go index 45f95c29..2604ddaf 100644 --- a/gen/go/google/api/http.pb.go +++ b/gen/go/google/api/http.pb.go @@ -14,7 +14,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc (unknown) // source: google/api/http.proto diff --git a/gen/go/types/value.pb.go b/gen/go/types/value.pb.go index 49fdc6dd..14e78418 100644 --- a/gen/go/types/value.pb.go +++ b/gen/go/types/value.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc (unknown) // source: types/value.proto diff --git a/gen/go/v1/config.pb.go b/gen/go/v1/config.pb.go index e4e0d62a..12e8e2a5 100644 --- a/gen/go/v1/config.pb.go +++ b/gen/go/v1/config.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc (unknown) // source: v1/config.proto @@ -32,6 +32,7 @@ type Config struct { Host string `protobuf:"bytes,2,opt,name=host,proto3" json:"host,omitempty"` Repos []*Repo `protobuf:"bytes,3,rep,name=repos,proto3" json:"repos,omitempty"` Plans []*Plan `protobuf:"bytes,4,rep,name=plans,proto3" json:"plans,omitempty"` + Users []*User `protobuf:"bytes,5,rep,name=users,proto3" json:"users,omitempty"` } func (x *Config) Reset() { @@ -94,6 +95,13 @@ func (x *Config) GetPlans() []*Plan { return nil } +func (x *Config) GetUsers() []*User { + if x != nil { + return x.Users + } + return nil +} + type Repo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -435,71 +443,153 @@ func (x *PrunePolicy) GetMaxUnusedBytes() int32 { return 0 } +type User struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Types that are assignable to Password: + // + // *User_PasswordBcrypt + Password isUser_Password `protobuf_oneof:"password"` +} + +func (x *User) Reset() { + *x = User{} + if protoimpl.UnsafeEnabled { + mi := &file_v1_config_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *User) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*User) ProtoMessage() {} + +func (x *User) ProtoReflect() protoreflect.Message { + mi := &file_v1_config_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use User.ProtoReflect.Descriptor instead. +func (*User) Descriptor() ([]byte, []int) { + return file_v1_config_proto_rawDescGZIP(), []int{5} +} + +func (x *User) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (m *User) GetPassword() isUser_Password { + if m != nil { + return m.Password + } + return nil +} + +func (x *User) GetPasswordBcrypt() string { + if x, ok := x.GetPassword().(*User_PasswordBcrypt); ok { + return x.PasswordBcrypt + } + return "" +} + +type isUser_Password interface { + isUser_Password() +} + +type User_PasswordBcrypt struct { + PasswordBcrypt string `protobuf:"bytes,2,opt,name=password_bcrypt,json=passwordBcrypt,proto3,oneof"` +} + +func (*User_PasswordBcrypt) isUser_Password() {} + var File_v1_config_proto protoreflect.FileDescriptor var file_v1_config_proto_rawDesc = []byte{ 0x0a, 0x0f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x02, 0x76, 0x31, 0x22, 0x72, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x6e, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, - 0x6d, 0x6f, 0x64, 0x6e, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x05, 0x72, 0x65, 0x70, - 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x70, 0x6f, 0x52, 0x05, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x12, 0x1e, 0x0a, 0x05, 0x70, 0x6c, 0x61, - 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, - 0x61, 0x6e, 0x52, 0x05, 0x70, 0x6c, 0x61, 0x6e, 0x73, 0x22, 0xa0, 0x01, 0x0a, 0x04, 0x52, 0x65, - 0x70, 0x6f, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x75, 0x72, 0x69, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, - 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x65, - 0x6e, 0x76, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x32, 0x0a, 0x0c, 0x70, 0x72, 0x75, 0x6e, - 0x65, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x75, 0x6e, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, - 0x0b, 0x70, 0x72, 0x75, 0x6e, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0xa3, 0x01, 0x0a, - 0x04, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x74, - 0x68, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x12, - 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, - 0x72, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x12, - 0x31, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x09, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0xb2, 0x02, 0x0a, 0x0f, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x6e, - 0x75, 0x73, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x55, 0x6e, 0x75, 0x73, 0x65, 0x64, 0x4c, 0x69, 0x6d, 0x69, 0x74, - 0x12, 0x1e, 0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x4c, 0x61, 0x73, 0x74, 0x4e, - 0x12, 0x1f, 0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x68, 0x6f, 0x75, 0x72, 0x6c, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6b, 0x65, 0x65, 0x70, 0x48, 0x6f, 0x75, 0x72, 0x6c, - 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, - 0x12, 0x1f, 0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6b, 0x65, 0x65, 0x70, 0x57, 0x65, 0x65, 0x6b, 0x6c, - 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, - 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x4d, 0x6f, 0x6e, - 0x74, 0x68, 0x6c, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x79, 0x65, 0x61, - 0x72, 0x6c, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6b, 0x65, 0x65, 0x70, 0x59, - 0x65, 0x61, 0x72, 0x6c, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x77, 0x69, - 0x74, 0x68, 0x69, 0x6e, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x12, 0x6b, 0x65, 0x65, 0x70, 0x57, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x93, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x75, 0x6e, - 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x6d, 0x61, 0x78, 0x5f, 0x66, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x64, 0x61, 0x79, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x46, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, - 0x79, 0x44, 0x61, 0x79, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x6e, 0x75, - 0x73, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x64, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x55, 0x6e, 0x75, 0x73, 0x65, 0x64, 0x50, 0x65, 0x72, 0x63, - 0x65, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x6e, 0x75, 0x73, 0x65, - 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x65, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6d, - 0x61, 0x78, 0x55, 0x6e, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x2e, 0x5a, - 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65, - 0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x72, 0x65, 0x73, - 0x74, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x12, 0x02, 0x76, 0x31, 0x22, 0x92, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x6e, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x05, 0x6d, 0x6f, 0x64, 0x6e, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x05, 0x72, 0x65, + 0x70, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x70, 0x6f, 0x52, 0x05, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x12, 0x1e, 0x0a, 0x05, 0x70, 0x6c, + 0x61, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x6c, 0x61, 0x6e, 0x52, 0x05, 0x70, 0x6c, 0x61, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x05, 0x75, 0x73, + 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x22, 0xa0, 0x01, 0x0a, 0x04, 0x52, + 0x65, 0x70, 0x6f, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, + 0x65, 0x6e, 0x76, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x32, 0x0a, 0x0c, 0x70, 0x72, 0x75, + 0x6e, 0x65, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0f, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x75, 0x6e, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x52, 0x0b, 0x70, 0x72, 0x75, 0x6e, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0xa3, 0x01, + 0x0a, 0x04, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, + 0x74, 0x68, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, + 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, + 0x63, 0x72, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x72, 0x6f, 0x6e, + 0x12, 0x31, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x09, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74, + 0x69, 0x6f, 0x6e, 0x22, 0xb2, 0x02, 0x0a, 0x0f, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, + 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x75, + 0x6e, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x55, 0x6e, 0x75, 0x73, 0x65, 0x64, 0x4c, 0x69, 0x6d, 0x69, + 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x4c, 0x61, 0x73, 0x74, + 0x4e, 0x12, 0x1f, 0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x68, 0x6f, 0x75, 0x72, 0x6c, 0x79, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6b, 0x65, 0x65, 0x70, 0x48, 0x6f, 0x75, 0x72, + 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x64, 0x61, 0x69, 0x6c, 0x79, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x44, 0x61, 0x69, 0x6c, + 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6b, 0x65, 0x65, 0x70, 0x57, 0x65, 0x65, 0x6b, + 0x6c, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x6d, 0x6f, 0x6e, 0x74, 0x68, + 0x6c, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x4d, 0x6f, + 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x79, 0x65, + 0x61, 0x72, 0x6c, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6b, 0x65, 0x65, 0x70, + 0x59, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x77, + 0x69, 0x74, 0x68, 0x69, 0x6e, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6b, 0x65, 0x65, 0x70, 0x57, 0x69, 0x74, 0x68, 0x69, 0x6e, + 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x93, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x75, + 0x6e, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x6d, 0x61, 0x78, 0x5f, + 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x64, 0x61, 0x79, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x46, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, + 0x63, 0x79, 0x44, 0x61, 0x79, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x6e, + 0x75, 0x73, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x64, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x55, 0x6e, 0x75, 0x73, 0x65, 0x64, 0x50, 0x65, 0x72, + 0x63, 0x65, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x6e, 0x75, 0x73, + 0x65, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x65, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, + 0x6d, 0x61, 0x78, 0x55, 0x6e, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x51, + 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x0f, 0x70, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x62, 0x63, 0x72, 0x79, 0x70, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0e, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x42, + 0x63, 0x72, 0x79, 0x70, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x67, 0x61, 0x72, 0x65, 0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x62, 0x61, 0x63, + 0x6b, 0x72, 0x65, 0x73, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -514,24 +604,26 @@ func file_v1_config_proto_rawDescGZIP() []byte { return file_v1_config_proto_rawDescData } -var file_v1_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_v1_config_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_v1_config_proto_goTypes = []interface{}{ (*Config)(nil), // 0: v1.Config (*Repo)(nil), // 1: v1.Repo (*Plan)(nil), // 2: v1.Plan (*RetentionPolicy)(nil), // 3: v1.RetentionPolicy (*PrunePolicy)(nil), // 4: v1.PrunePolicy + (*User)(nil), // 5: v1.User } var file_v1_config_proto_depIdxs = []int32{ 1, // 0: v1.Config.repos:type_name -> v1.Repo 2, // 1: v1.Config.plans:type_name -> v1.Plan - 4, // 2: v1.Repo.prune_policy:type_name -> v1.PrunePolicy - 3, // 3: v1.Plan.retention:type_name -> v1.RetentionPolicy - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 5, // 2: v1.Config.users:type_name -> v1.User + 4, // 3: v1.Repo.prune_policy:type_name -> v1.PrunePolicy + 3, // 4: v1.Plan.retention:type_name -> v1.RetentionPolicy + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_v1_config_proto_init() } @@ -600,6 +692,21 @@ func file_v1_config_proto_init() { return nil } } + file_v1_config_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*User); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_v1_config_proto_msgTypes[5].OneofWrappers = []interface{}{ + (*User_PasswordBcrypt)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -607,7 +714,7 @@ func file_v1_config_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_v1_config_proto_rawDesc, NumEnums: 0, - NumMessages: 5, + NumMessages: 6, NumExtensions: 0, NumServices: 0, }, diff --git a/gen/go/v1/events.pb.go b/gen/go/v1/events.pb.go deleted file mode 100644 index a3b19ab6..00000000 --- a/gen/go/v1/events.pb.go +++ /dev/null @@ -1,405 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc (unknown) -// source: v1/events.proto - -package v1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type Status int32 - -const ( - Status_UNKNOWN Status = 0 - Status_IN_PROGRESS Status = 1 - Status_SUCCESS Status = 2 - Status_FAILED Status = 3 -) - -// Enum value maps for Status. -var ( - Status_name = map[int32]string{ - 0: "UNKNOWN", - 1: "IN_PROGRESS", - 2: "SUCCESS", - 3: "FAILED", - } - Status_value = map[string]int32{ - "UNKNOWN": 0, - "IN_PROGRESS": 1, - "SUCCESS": 2, - "FAILED": 3, - } -) - -func (x Status) Enum() *Status { - p := new(Status) - *p = x - return p -} - -func (x Status) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Status) Descriptor() protoreflect.EnumDescriptor { - return file_v1_events_proto_enumTypes[0].Descriptor() -} - -func (Status) Type() protoreflect.EnumType { - return &file_v1_events_proto_enumTypes[0] -} - -func (x Status) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Status.Descriptor instead. -func (Status) EnumDescriptor() ([]byte, []int) { - return file_v1_events_proto_rawDescGZIP(), []int{0} -} - -type Event struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // timestamp is the number of milliseconds since the Unix epoch. - Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - // Types that are assignable to Event: - // - // *Event_Log - // *Event_BackupStatusChange - Event isEvent_Event `protobuf_oneof:"event"` -} - -func (x *Event) Reset() { - *x = Event{} - if protoimpl.UnsafeEnabled { - mi := &file_v1_events_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Event) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Event) ProtoMessage() {} - -func (x *Event) ProtoReflect() protoreflect.Message { - mi := &file_v1_events_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Event.ProtoReflect.Descriptor instead. -func (*Event) Descriptor() ([]byte, []int) { - return file_v1_events_proto_rawDescGZIP(), []int{0} -} - -func (x *Event) GetTimestamp() int64 { - if x != nil { - return x.Timestamp - } - return 0 -} - -func (m *Event) GetEvent() isEvent_Event { - if m != nil { - return m.Event - } - return nil -} - -func (x *Event) GetLog() *LogEvent { - if x, ok := x.GetEvent().(*Event_Log); ok { - return x.Log - } - return nil -} - -func (x *Event) GetBackupStatusChange() *BackupStatusEvent { - if x, ok := x.GetEvent().(*Event_BackupStatusChange); ok { - return x.BackupStatusChange - } - return nil -} - -type isEvent_Event interface { - isEvent_Event() -} - -type Event_Log struct { - Log *LogEvent `protobuf:"bytes,3,opt,name=log,proto3,oneof"` -} - -type Event_BackupStatusChange struct { - BackupStatusChange *BackupStatusEvent `protobuf:"bytes,4,opt,name=backup_status_change,json=backupStatusChange,proto3,oneof"` -} - -func (*Event_Log) isEvent_Event() {} - -func (*Event_BackupStatusChange) isEvent_Event() {} - -type LogEvent struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` -} - -func (x *LogEvent) Reset() { - *x = LogEvent{} - if protoimpl.UnsafeEnabled { - mi := &file_v1_events_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LogEvent) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LogEvent) ProtoMessage() {} - -func (x *LogEvent) ProtoReflect() protoreflect.Message { - mi := &file_v1_events_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LogEvent.ProtoReflect.Descriptor instead. -func (*LogEvent) Descriptor() ([]byte, []int) { - return file_v1_events_proto_rawDescGZIP(), []int{1} -} - -func (x *LogEvent) GetMessage() string { - if x != nil { - return x.Message - } - return "" -} - -type BackupStatusEvent struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Plan string `protobuf:"bytes,1,opt,name=plan,proto3" json:"plan,omitempty"` - Status Status `protobuf:"varint,2,opt,name=status,proto3,enum=v1.Status" json:"status,omitempty"` - Percent uint32 `protobuf:"varint,3,opt,name=percent,proto3" json:"percent,omitempty"` -} - -func (x *BackupStatusEvent) Reset() { - *x = BackupStatusEvent{} - if protoimpl.UnsafeEnabled { - mi := &file_v1_events_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BackupStatusEvent) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BackupStatusEvent) ProtoMessage() {} - -func (x *BackupStatusEvent) ProtoReflect() protoreflect.Message { - mi := &file_v1_events_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BackupStatusEvent.ProtoReflect.Descriptor instead. -func (*BackupStatusEvent) Descriptor() ([]byte, []int) { - return file_v1_events_proto_rawDescGZIP(), []int{2} -} - -func (x *BackupStatusEvent) GetPlan() string { - if x != nil { - return x.Plan - } - return "" -} - -func (x *BackupStatusEvent) GetStatus() Status { - if x != nil { - return x.Status - } - return Status_UNKNOWN -} - -func (x *BackupStatusEvent) GetPercent() uint32 { - if x != nil { - return x.Percent - } - return 0 -} - -var File_v1_events_proto protoreflect.FileDescriptor - -var file_v1_events_proto_rawDesc = []byte{ - 0x0a, 0x0f, 0x76, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x02, 0x76, 0x31, 0x22, 0x9b, 0x01, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, - 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x20, 0x0a, - 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x6f, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, - 0x49, 0x0a, 0x14, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, - 0x76, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x12, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x22, 0x24, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, - 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x65, 0x0a, 0x11, 0x42, 0x61, 0x63, - 0x6b, 0x75, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6c, - 0x61, 0x6e, 0x12, 0x22, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, - 0x2a, 0x3f, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, - 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x4e, 0x5f, 0x50, 0x52, - 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x43, 0x43, - 0x45, 0x53, 0x53, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, - 0x03, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x67, 0x61, 0x72, 0x65, 0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x72, 0x65, 0x73, - 0x74, 0x69, 0x63, 0x75, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_v1_events_proto_rawDescOnce sync.Once - file_v1_events_proto_rawDescData = file_v1_events_proto_rawDesc -) - -func file_v1_events_proto_rawDescGZIP() []byte { - file_v1_events_proto_rawDescOnce.Do(func() { - file_v1_events_proto_rawDescData = protoimpl.X.CompressGZIP(file_v1_events_proto_rawDescData) - }) - return file_v1_events_proto_rawDescData -} - -var file_v1_events_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_v1_events_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_v1_events_proto_goTypes = []interface{}{ - (Status)(0), // 0: v1.Status - (*Event)(nil), // 1: v1.Event - (*LogEvent)(nil), // 2: v1.LogEvent - (*BackupStatusEvent)(nil), // 3: v1.BackupStatusEvent -} -var file_v1_events_proto_depIdxs = []int32{ - 2, // 0: v1.Event.log:type_name -> v1.LogEvent - 3, // 1: v1.Event.backup_status_change:type_name -> v1.BackupStatusEvent - 0, // 2: v1.BackupStatusEvent.status:type_name -> v1.Status - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name -} - -func init() { file_v1_events_proto_init() } -func file_v1_events_proto_init() { - if File_v1_events_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_v1_events_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Event); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_v1_events_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LogEvent); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_v1_events_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BackupStatusEvent); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_v1_events_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*Event_Log)(nil), - (*Event_BackupStatusChange)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_v1_events_proto_rawDesc, - NumEnums: 1, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_v1_events_proto_goTypes, - DependencyIndexes: file_v1_events_proto_depIdxs, - EnumInfos: file_v1_events_proto_enumTypes, - MessageInfos: file_v1_events_proto_msgTypes, - }.Build() - File_v1_events_proto = out.File - file_v1_events_proto_rawDesc = nil - file_v1_events_proto_goTypes = nil - file_v1_events_proto_depIdxs = nil -} diff --git a/gen/go/v1/operations.pb.go b/gen/go/v1/operations.pb.go index c771d6d5..80dc989a 100644 --- a/gen/go/v1/operations.pb.go +++ b/gen/go/v1/operations.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc (unknown) // source: v1/operations.proto @@ -817,11 +817,10 @@ var file_v1_operations_proto_rawDesc = []byte{ 0x10, 0x04, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x43, - 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x06, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, + 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x06, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65, 0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x72, 0x65, 0x73, 0x74, 0x2f, 0x67, - 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/gen/go/v1/restic.pb.go b/gen/go/v1/restic.pb.go index 43965f48..523ecfdc 100644 --- a/gen/go/v1/restic.pb.go +++ b/gen/go/v1/restic.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc (unknown) // source: v1/restic.proto @@ -676,10 +676,10 @@ var file_v1_restic_proto_rawDesc = []byte{ 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x6f, 0x6e, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x70, 0x65, 0x72, - 0x63, 0x65, 0x6e, 0x74, 0x44, 0x6f, 0x6e, 0x65, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, + 0x63, 0x65, 0x6e, 0x74, 0x44, 0x6f, 0x6e, 0x65, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65, 0x74, 0x68, 0x67, 0x65, 0x6f, - 0x72, 0x67, 0x65, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x72, 0x65, 0x73, 0x74, 0x2f, 0x67, 0x6f, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x67, 0x65, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x72, 0x65, 0x73, 0x74, 0x2f, 0x67, 0x65, 0x6e, + 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/gen/go/v1/service.pb.go b/gen/go/v1/service.pb.go index aeb666c7..081471c0 100644 --- a/gen/go/v1/service.pb.go +++ b/gen/go/v1/service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc (unknown) // source: v1/service.proto @@ -604,91 +604,66 @@ var file_v1_service_proto_rawDesc = []byte{ 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x63, 0x74, 0x69, 0x6d, 0x65, 0x32, 0x80, 0x0a, 0x0a, 0x08, 0x42, 0x61, 0x63, 0x6b, 0x72, - 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x05, 0x63, 0x74, 0x69, 0x6d, 0x65, 0x32, 0xfd, 0x06, 0x0a, 0x08, 0x42, 0x61, 0x63, 0x6b, 0x72, + 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x12, 0x0a, 0x2f, 0x76, - 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x1a, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x15, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x3a, 0x01, 0x2a, 0x22, 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x12, - 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x1a, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x3a, 0x01, 0x2a, - 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x65, 0x70, - 0x6f, 0x12, 0x61, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, - 0x12, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, - 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x30, 0x01, 0x12, 0x57, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x11, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, - 0x73, 0x74, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, - 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5b, 0x0a, - 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x12, 0x18, + 0x6e, 0x66, 0x69, 0x67, 0x22, 0x00, 0x12, 0x25, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, + 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x00, 0x12, 0x21, 0x0a, + 0x07, 0x41, 0x64, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x12, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x70, 0x6f, 0x1a, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x00, + 0x12, 0x44, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, + 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, 0x3e, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x11, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x69, 0x63, 0x53, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x12, 0x52, 0x0a, 0x11, 0x4c, + 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x12, 0x1c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, + 0x6f, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x73, 0x74, 0x69, 0x63, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4c, 0x69, 0x73, 0x74, - 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, 0x01, 0x2a, 0x22, 0x0d, 0x2f, 0x76, 0x31, - 0x2f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x12, 0x70, 0x0a, 0x11, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, - 0x1c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, - 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x46, - 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x4f, 0x0a, 0x06, - 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, - 0x76, 0x31, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x4d, 0x0a, - 0x05, 0x50, 0x72, 0x75, 0x6e, 0x65, 0x12, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, 0x01, 0x2a, 0x22, 0x0d, 0x2f, - 0x76, 0x31, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x75, 0x6e, 0x65, 0x12, 0x4f, 0x0a, 0x06, - 0x46, 0x6f, 0x72, 0x67, 0x65, 0x74, 0x12, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, - 0x76, 0x31, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x74, 0x12, 0x59, 0x0a, - 0x07, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x1a, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x1a, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x14, 0x3a, 0x01, 0x2a, 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6d, 0x64, - 0x2f, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x4f, 0x0a, 0x06, 0x55, 0x6e, 0x6c, 0x6f, - 0x63, 0x6b, 0x12, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x19, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x63, - 0x6d, 0x64, 0x2f, 0x75, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x4e, 0x0a, 0x06, 0x43, 0x61, 0x6e, - 0x63, 0x65, 0x6c, 0x12, 0x11, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x36, - 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x19, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x63, - 0x6d, 0x64, 0x2f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x12, 0x61, 0x0a, 0x0c, 0x43, 0x6c, 0x65, - 0x61, 0x72, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x17, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x6c, 0x65, 0x61, 0x72, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x63, - 0x6c, 0x65, 0x61, 0x72, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x5b, 0x0a, 0x10, - 0x50, 0x61, 0x74, 0x68, 0x41, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, + 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x36, 0x0a, 0x06, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x05, 0x50, 0x72, 0x75, 0x6e, 0x65, 0x12, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x11, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x3a, - 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, - 0x6c, 0x65, 0x74, 0x65, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65, 0x74, 0x68, 0x67, 0x65, - 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x72, 0x65, 0x73, 0x74, 0x2f, 0x67, 0x6f, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x36, + 0x0a, 0x06, 0x46, 0x6f, 0x72, 0x67, 0x65, 0x74, 0x12, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, + 0x65, 0x12, 0x1a, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x06, 0x55, 0x6e, 0x6c, 0x6f, 0x63, + 0x6b, 0x12, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, + 0x35, 0x0a, 0x06, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x12, 0x11, 0x2e, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x0c, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x48, + 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x17, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, + 0x72, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x10, 0x50, 0x61, 0x74, + 0x68, 0x41, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x12, 0x2e, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x1a, 0x11, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65, 0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, + 0x65, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x72, 0x65, 0x73, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, + 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/gen/go/v1/service.pb.gw.go b/gen/go/v1/service.pb.gw.go deleted file mode 100644 index d1183244..00000000 --- a/gen/go/v1/service.pb.gw.go +++ /dev/null @@ -1,1312 +0,0 @@ -// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. -// source: v1/service.proto - -/* -Package v1 is a reverse proxy. - -It translates gRPC into RESTful JSON APIs. -*/ -package v1 - -import ( - "context" - "io" - "net/http" - - "github.com/garethgeorge/backrest/gen/go/types" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/grpclog" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/emptypb" -) - -// Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = metadata.Join - -func request_Backrest_GetConfig_0(ctx context.Context, marshaler runtime.Marshaler, client BackrestClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := client.GetConfig(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Backrest_GetConfig_0(ctx context.Context, marshaler runtime.Marshaler, server BackrestServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := server.GetConfig(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Backrest_SetConfig_0(ctx context.Context, marshaler runtime.Marshaler, client BackrestClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Config - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.SetConfig(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Backrest_SetConfig_0(ctx context.Context, marshaler runtime.Marshaler, server BackrestServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Config - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.SetConfig(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Backrest_AddRepo_0(ctx context.Context, marshaler runtime.Marshaler, client BackrestClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Repo - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.AddRepo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Backrest_AddRepo_0(ctx context.Context, marshaler runtime.Marshaler, server BackrestServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Repo - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.AddRepo(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Backrest_GetOperationEvents_0(ctx context.Context, marshaler runtime.Marshaler, client BackrestClient, req *http.Request, pathParams map[string]string) (Backrest_GetOperationEventsClient, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - stream, err := client.GetOperationEvents(ctx, &protoReq) - if err != nil { - return nil, metadata, err - } - header, err := stream.Header() - if err != nil { - return nil, metadata, err - } - metadata.HeaderMD = header - return stream, metadata, nil - -} - -func request_Backrest_GetOperations_0(ctx context.Context, marshaler runtime.Marshaler, client BackrestClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetOperationsRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetOperations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Backrest_GetOperations_0(ctx context.Context, marshaler runtime.Marshaler, server BackrestServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetOperationsRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetOperations(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Backrest_ListSnapshots_0(ctx context.Context, marshaler runtime.Marshaler, client BackrestClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListSnapshotsRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ListSnapshots(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Backrest_ListSnapshots_0(ctx context.Context, marshaler runtime.Marshaler, server BackrestServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListSnapshotsRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ListSnapshots(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Backrest_ListSnapshotFiles_0(ctx context.Context, marshaler runtime.Marshaler, client BackrestClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListSnapshotFilesRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ListSnapshotFiles(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Backrest_ListSnapshotFiles_0(ctx context.Context, marshaler runtime.Marshaler, server BackrestServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListSnapshotFilesRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ListSnapshotFiles(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Backrest_Backup_0(ctx context.Context, marshaler runtime.Marshaler, client BackrestClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq types.StringValue - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.Backup(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Backrest_Backup_0(ctx context.Context, marshaler runtime.Marshaler, server BackrestServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq types.StringValue - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.Backup(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Backrest_Prune_0(ctx context.Context, marshaler runtime.Marshaler, client BackrestClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq types.StringValue - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.Prune(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Backrest_Prune_0(ctx context.Context, marshaler runtime.Marshaler, server BackrestServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq types.StringValue - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.Prune(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Backrest_Forget_0(ctx context.Context, marshaler runtime.Marshaler, client BackrestClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq types.StringValue - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.Forget(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Backrest_Forget_0(ctx context.Context, marshaler runtime.Marshaler, server BackrestServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq types.StringValue - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.Forget(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Backrest_Restore_0(ctx context.Context, marshaler runtime.Marshaler, client BackrestClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq RestoreSnapshotRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.Restore(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Backrest_Restore_0(ctx context.Context, marshaler runtime.Marshaler, server BackrestServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq RestoreSnapshotRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.Restore(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Backrest_Unlock_0(ctx context.Context, marshaler runtime.Marshaler, client BackrestClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq types.StringValue - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.Unlock(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Backrest_Unlock_0(ctx context.Context, marshaler runtime.Marshaler, server BackrestServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq types.StringValue - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.Unlock(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Backrest_Cancel_0(ctx context.Context, marshaler runtime.Marshaler, client BackrestClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq types.Int64Value - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.Cancel(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Backrest_Cancel_0(ctx context.Context, marshaler runtime.Marshaler, server BackrestServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq types.Int64Value - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.Cancel(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Backrest_ClearHistory_0(ctx context.Context, marshaler runtime.Marshaler, client BackrestClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ClearHistoryRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ClearHistory(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Backrest_ClearHistory_0(ctx context.Context, marshaler runtime.Marshaler, server BackrestServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ClearHistoryRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ClearHistory(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Backrest_PathAutocomplete_0(ctx context.Context, marshaler runtime.Marshaler, client BackrestClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq types.StringValue - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.PathAutocomplete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Backrest_PathAutocomplete_0(ctx context.Context, marshaler runtime.Marshaler, server BackrestServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq types.StringValue - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.PathAutocomplete(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterBackrestHandlerServer registers the http handlers for service Backrest to "mux". -// UnaryRPC :call BackrestServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterBackrestHandlerFromEndpoint instead. -func RegisterBackrestHandlerServer(ctx context.Context, mux *runtime.ServeMux, server BackrestServer) error { - - mux.Handle("GET", pattern_Backrest_GetConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/v1.Backrest/GetConfig", runtime.WithHTTPPathPattern("/v1/config")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Backrest_GetConfig_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_GetConfig_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_SetConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/v1.Backrest/SetConfig", runtime.WithHTTPPathPattern("/v1/config")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Backrest_SetConfig_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_SetConfig_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_AddRepo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/v1.Backrest/AddRepo", runtime.WithHTTPPathPattern("/v1/config/repo")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Backrest_AddRepo_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_AddRepo_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Backrest_GetOperationEvents_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") - _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - }) - - mux.Handle("POST", pattern_Backrest_GetOperations_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/v1.Backrest/GetOperations", runtime.WithHTTPPathPattern("/v1/operations")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Backrest_GetOperations_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_GetOperations_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_ListSnapshots_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/v1.Backrest/ListSnapshots", runtime.WithHTTPPathPattern("/v1/snapshots")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Backrest_ListSnapshots_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_ListSnapshots_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_ListSnapshotFiles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/v1.Backrest/ListSnapshotFiles", runtime.WithHTTPPathPattern("/v1/snapshots/files")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Backrest_ListSnapshotFiles_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_ListSnapshotFiles_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_Backup_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/v1.Backrest/Backup", runtime.WithHTTPPathPattern("/v1/cmd/backup")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Backrest_Backup_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_Backup_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_Prune_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/v1.Backrest/Prune", runtime.WithHTTPPathPattern("/v1/cmd/prune")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Backrest_Prune_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_Prune_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_Forget_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/v1.Backrest/Forget", runtime.WithHTTPPathPattern("/v1/cmd/forget")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Backrest_Forget_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_Forget_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_Restore_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/v1.Backrest/Restore", runtime.WithHTTPPathPattern("/v1/cmd/restore")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Backrest_Restore_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_Restore_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_Unlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/v1.Backrest/Unlock", runtime.WithHTTPPathPattern("/v1/cmd/unlock")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Backrest_Unlock_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_Unlock_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_Cancel_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/v1.Backrest/Cancel", runtime.WithHTTPPathPattern("/v1/cmd/cancel")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Backrest_Cancel_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_Cancel_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_ClearHistory_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/v1.Backrest/ClearHistory", runtime.WithHTTPPathPattern("/v1/cmd/clear_history")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Backrest_ClearHistory_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_ClearHistory_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_PathAutocomplete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/v1.Backrest/PathAutocomplete", runtime.WithHTTPPathPattern("/v1/autocomplete/path")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Backrest_PathAutocomplete_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_PathAutocomplete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -// RegisterBackrestHandlerFromEndpoint is same as RegisterBackrestHandler but -// automatically dials to "endpoint" and closes the connection when "ctx" gets done. -func RegisterBackrestHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.DialContext(ctx, endpoint, opts...) - if err != nil { - return err - } - defer func() { - if err != nil { - if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) - } - return - } - go func() { - <-ctx.Done() - if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) - } - }() - }() - - return RegisterBackrestHandler(ctx, mux, conn) -} - -// RegisterBackrestHandler registers the http handlers for service Backrest to "mux". -// The handlers forward requests to the grpc endpoint over "conn". -func RegisterBackrestHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { - return RegisterBackrestHandlerClient(ctx, mux, NewBackrestClient(conn)) -} - -// RegisterBackrestHandlerClient registers the http handlers for service Backrest -// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "BackrestClient". -// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "BackrestClient" -// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "BackrestClient" to call the correct interceptors. -func RegisterBackrestHandlerClient(ctx context.Context, mux *runtime.ServeMux, client BackrestClient) error { - - mux.Handle("GET", pattern_Backrest_GetConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/v1.Backrest/GetConfig", runtime.WithHTTPPathPattern("/v1/config")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Backrest_GetConfig_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_GetConfig_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_SetConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/v1.Backrest/SetConfig", runtime.WithHTTPPathPattern("/v1/config")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Backrest_SetConfig_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_SetConfig_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_AddRepo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/v1.Backrest/AddRepo", runtime.WithHTTPPathPattern("/v1/config/repo")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Backrest_AddRepo_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_AddRepo_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Backrest_GetOperationEvents_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/v1.Backrest/GetOperationEvents", runtime.WithHTTPPathPattern("/v1/events/operations")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Backrest_GetOperationEvents_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_GetOperationEvents_0(annotatedContext, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_GetOperations_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/v1.Backrest/GetOperations", runtime.WithHTTPPathPattern("/v1/operations")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Backrest_GetOperations_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_GetOperations_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_ListSnapshots_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/v1.Backrest/ListSnapshots", runtime.WithHTTPPathPattern("/v1/snapshots")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Backrest_ListSnapshots_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_ListSnapshots_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_ListSnapshotFiles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/v1.Backrest/ListSnapshotFiles", runtime.WithHTTPPathPattern("/v1/snapshots/files")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Backrest_ListSnapshotFiles_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_ListSnapshotFiles_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_Backup_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/v1.Backrest/Backup", runtime.WithHTTPPathPattern("/v1/cmd/backup")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Backrest_Backup_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_Backup_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_Prune_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/v1.Backrest/Prune", runtime.WithHTTPPathPattern("/v1/cmd/prune")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Backrest_Prune_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_Prune_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_Forget_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/v1.Backrest/Forget", runtime.WithHTTPPathPattern("/v1/cmd/forget")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Backrest_Forget_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_Forget_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_Restore_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/v1.Backrest/Restore", runtime.WithHTTPPathPattern("/v1/cmd/restore")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Backrest_Restore_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_Restore_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_Unlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/v1.Backrest/Unlock", runtime.WithHTTPPathPattern("/v1/cmd/unlock")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Backrest_Unlock_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_Unlock_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_Cancel_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/v1.Backrest/Cancel", runtime.WithHTTPPathPattern("/v1/cmd/cancel")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Backrest_Cancel_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_Cancel_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_ClearHistory_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/v1.Backrest/ClearHistory", runtime.WithHTTPPathPattern("/v1/cmd/clear_history")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Backrest_ClearHistory_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_ClearHistory_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Backrest_PathAutocomplete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/v1.Backrest/PathAutocomplete", runtime.WithHTTPPathPattern("/v1/autocomplete/path")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Backrest_PathAutocomplete_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Backrest_PathAutocomplete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -var ( - pattern_Backrest_GetConfig_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "config"}, "")) - - pattern_Backrest_SetConfig_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "config"}, "")) - - pattern_Backrest_AddRepo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "config", "repo"}, "")) - - pattern_Backrest_GetOperationEvents_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "events", "operations"}, "")) - - pattern_Backrest_GetOperations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "operations"}, "")) - - pattern_Backrest_ListSnapshots_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "snapshots"}, "")) - - pattern_Backrest_ListSnapshotFiles_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "snapshots", "files"}, "")) - - pattern_Backrest_Backup_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "cmd", "backup"}, "")) - - pattern_Backrest_Prune_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "cmd", "prune"}, "")) - - pattern_Backrest_Forget_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "cmd", "forget"}, "")) - - pattern_Backrest_Restore_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "cmd", "restore"}, "")) - - pattern_Backrest_Unlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "cmd", "unlock"}, "")) - - pattern_Backrest_Cancel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "cmd", "cancel"}, "")) - - pattern_Backrest_ClearHistory_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "cmd", "clear_history"}, "")) - - pattern_Backrest_PathAutocomplete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "autocomplete", "path"}, "")) -) - -var ( - forward_Backrest_GetConfig_0 = runtime.ForwardResponseMessage - - forward_Backrest_SetConfig_0 = runtime.ForwardResponseMessage - - forward_Backrest_AddRepo_0 = runtime.ForwardResponseMessage - - forward_Backrest_GetOperationEvents_0 = runtime.ForwardResponseStream - - forward_Backrest_GetOperations_0 = runtime.ForwardResponseMessage - - forward_Backrest_ListSnapshots_0 = runtime.ForwardResponseMessage - - forward_Backrest_ListSnapshotFiles_0 = runtime.ForwardResponseMessage - - forward_Backrest_Backup_0 = runtime.ForwardResponseMessage - - forward_Backrest_Prune_0 = runtime.ForwardResponseMessage - - forward_Backrest_Forget_0 = runtime.ForwardResponseMessage - - forward_Backrest_Restore_0 = runtime.ForwardResponseMessage - - forward_Backrest_Unlock_0 = runtime.ForwardResponseMessage - - forward_Backrest_Cancel_0 = runtime.ForwardResponseMessage - - forward_Backrest_ClearHistory_0 = runtime.ForwardResponseMessage - - forward_Backrest_PathAutocomplete_0 = runtime.ForwardResponseMessage -) diff --git a/gen/go/v1/v1connect/service.connect.go b/gen/go/v1/v1connect/service.connect.go new file mode 100644 index 00000000..25ba08e0 --- /dev/null +++ b/gen/go/v1/v1connect/service.connect.go @@ -0,0 +1,537 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: v1/service.proto + +package v1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + types "github.com/garethgeorge/backrest/gen/go/types" + v1 "github.com/garethgeorge/backrest/gen/go/v1" + emptypb "google.golang.org/protobuf/types/known/emptypb" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // BackrestName is the fully-qualified name of the Backrest service. + BackrestName = "v1.Backrest" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // BackrestGetConfigProcedure is the fully-qualified name of the Backrest's GetConfig RPC. + BackrestGetConfigProcedure = "/v1.Backrest/GetConfig" + // BackrestSetConfigProcedure is the fully-qualified name of the Backrest's SetConfig RPC. + BackrestSetConfigProcedure = "/v1.Backrest/SetConfig" + // BackrestAddRepoProcedure is the fully-qualified name of the Backrest's AddRepo RPC. + BackrestAddRepoProcedure = "/v1.Backrest/AddRepo" + // BackrestGetOperationEventsProcedure is the fully-qualified name of the Backrest's + // GetOperationEvents RPC. + BackrestGetOperationEventsProcedure = "/v1.Backrest/GetOperationEvents" + // BackrestGetOperationsProcedure is the fully-qualified name of the Backrest's GetOperations RPC. + BackrestGetOperationsProcedure = "/v1.Backrest/GetOperations" + // BackrestListSnapshotsProcedure is the fully-qualified name of the Backrest's ListSnapshots RPC. + BackrestListSnapshotsProcedure = "/v1.Backrest/ListSnapshots" + // BackrestListSnapshotFilesProcedure is the fully-qualified name of the Backrest's + // ListSnapshotFiles RPC. + BackrestListSnapshotFilesProcedure = "/v1.Backrest/ListSnapshotFiles" + // BackrestBackupProcedure is the fully-qualified name of the Backrest's Backup RPC. + BackrestBackupProcedure = "/v1.Backrest/Backup" + // BackrestPruneProcedure is the fully-qualified name of the Backrest's Prune RPC. + BackrestPruneProcedure = "/v1.Backrest/Prune" + // BackrestForgetProcedure is the fully-qualified name of the Backrest's Forget RPC. + BackrestForgetProcedure = "/v1.Backrest/Forget" + // BackrestRestoreProcedure is the fully-qualified name of the Backrest's Restore RPC. + BackrestRestoreProcedure = "/v1.Backrest/Restore" + // BackrestUnlockProcedure is the fully-qualified name of the Backrest's Unlock RPC. + BackrestUnlockProcedure = "/v1.Backrest/Unlock" + // BackrestCancelProcedure is the fully-qualified name of the Backrest's Cancel RPC. + BackrestCancelProcedure = "/v1.Backrest/Cancel" + // BackrestClearHistoryProcedure is the fully-qualified name of the Backrest's ClearHistory RPC. + BackrestClearHistoryProcedure = "/v1.Backrest/ClearHistory" + // BackrestPathAutocompleteProcedure is the fully-qualified name of the Backrest's PathAutocomplete + // RPC. + BackrestPathAutocompleteProcedure = "/v1.Backrest/PathAutocomplete" +) + +// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. +var ( + backrestServiceDescriptor = v1.File_v1_service_proto.Services().ByName("Backrest") + backrestGetConfigMethodDescriptor = backrestServiceDescriptor.Methods().ByName("GetConfig") + backrestSetConfigMethodDescriptor = backrestServiceDescriptor.Methods().ByName("SetConfig") + backrestAddRepoMethodDescriptor = backrestServiceDescriptor.Methods().ByName("AddRepo") + backrestGetOperationEventsMethodDescriptor = backrestServiceDescriptor.Methods().ByName("GetOperationEvents") + backrestGetOperationsMethodDescriptor = backrestServiceDescriptor.Methods().ByName("GetOperations") + backrestListSnapshotsMethodDescriptor = backrestServiceDescriptor.Methods().ByName("ListSnapshots") + backrestListSnapshotFilesMethodDescriptor = backrestServiceDescriptor.Methods().ByName("ListSnapshotFiles") + backrestBackupMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Backup") + backrestPruneMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Prune") + backrestForgetMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Forget") + backrestRestoreMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Restore") + backrestUnlockMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Unlock") + backrestCancelMethodDescriptor = backrestServiceDescriptor.Methods().ByName("Cancel") + backrestClearHistoryMethodDescriptor = backrestServiceDescriptor.Methods().ByName("ClearHistory") + backrestPathAutocompleteMethodDescriptor = backrestServiceDescriptor.Methods().ByName("PathAutocomplete") +) + +// BackrestClient is a client for the v1.Backrest service. +type BackrestClient interface { + GetConfig(context.Context, *connect.Request[emptypb.Empty]) (*connect.Response[v1.Config], error) + SetConfig(context.Context, *connect.Request[v1.Config]) (*connect.Response[v1.Config], error) + AddRepo(context.Context, *connect.Request[v1.Repo]) (*connect.Response[v1.Config], error) + GetOperationEvents(context.Context, *connect.Request[emptypb.Empty]) (*connect.ServerStreamForClient[v1.OperationEvent], error) + GetOperations(context.Context, *connect.Request[v1.GetOperationsRequest]) (*connect.Response[v1.OperationList], error) + ListSnapshots(context.Context, *connect.Request[v1.ListSnapshotsRequest]) (*connect.Response[v1.ResticSnapshotList], error) + ListSnapshotFiles(context.Context, *connect.Request[v1.ListSnapshotFilesRequest]) (*connect.Response[v1.ListSnapshotFilesResponse], error) + // Backup schedules a backup operation. It accepts a plan id and returns empty if the task is enqueued. + Backup(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) + // Prune schedules a prune operation. + Prune(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) + // Forget schedules a forget operation. + Forget(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) + // Restore schedules a restore operation. + Restore(context.Context, *connect.Request[v1.RestoreSnapshotRequest]) (*connect.Response[emptypb.Empty], error) + // Unlock synchronously attempts to unlock the repo. Will block if other operations are in progress. + Unlock(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) + // Cancel attempts to cancel a task with the given operation ID. Not guaranteed to succeed. + Cancel(context.Context, *connect.Request[types.Int64Value]) (*connect.Response[emptypb.Empty], error) + ClearHistory(context.Context, *connect.Request[v1.ClearHistoryRequest]) (*connect.Response[emptypb.Empty], error) + // PathAutocomplete provides path autocompletion options for a given filesystem path. + PathAutocomplete(context.Context, *connect.Request[types.StringValue]) (*connect.Response[types.StringList], error) +} + +// NewBackrestClient constructs a client for the v1.Backrest service. By default, it uses the +// Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends +// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or +// connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewBackrestClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) BackrestClient { + baseURL = strings.TrimRight(baseURL, "/") + return &backrestClient{ + getConfig: connect.NewClient[emptypb.Empty, v1.Config]( + httpClient, + baseURL+BackrestGetConfigProcedure, + connect.WithSchema(backrestGetConfigMethodDescriptor), + connect.WithClientOptions(opts...), + ), + setConfig: connect.NewClient[v1.Config, v1.Config]( + httpClient, + baseURL+BackrestSetConfigProcedure, + connect.WithSchema(backrestSetConfigMethodDescriptor), + connect.WithClientOptions(opts...), + ), + addRepo: connect.NewClient[v1.Repo, v1.Config]( + httpClient, + baseURL+BackrestAddRepoProcedure, + connect.WithSchema(backrestAddRepoMethodDescriptor), + connect.WithClientOptions(opts...), + ), + getOperationEvents: connect.NewClient[emptypb.Empty, v1.OperationEvent]( + httpClient, + baseURL+BackrestGetOperationEventsProcedure, + connect.WithSchema(backrestGetOperationEventsMethodDescriptor), + connect.WithClientOptions(opts...), + ), + getOperations: connect.NewClient[v1.GetOperationsRequest, v1.OperationList]( + httpClient, + baseURL+BackrestGetOperationsProcedure, + connect.WithSchema(backrestGetOperationsMethodDescriptor), + connect.WithClientOptions(opts...), + ), + listSnapshots: connect.NewClient[v1.ListSnapshotsRequest, v1.ResticSnapshotList]( + httpClient, + baseURL+BackrestListSnapshotsProcedure, + connect.WithSchema(backrestListSnapshotsMethodDescriptor), + connect.WithClientOptions(opts...), + ), + listSnapshotFiles: connect.NewClient[v1.ListSnapshotFilesRequest, v1.ListSnapshotFilesResponse]( + httpClient, + baseURL+BackrestListSnapshotFilesProcedure, + connect.WithSchema(backrestListSnapshotFilesMethodDescriptor), + connect.WithClientOptions(opts...), + ), + backup: connect.NewClient[types.StringValue, emptypb.Empty]( + httpClient, + baseURL+BackrestBackupProcedure, + connect.WithSchema(backrestBackupMethodDescriptor), + connect.WithClientOptions(opts...), + ), + prune: connect.NewClient[types.StringValue, emptypb.Empty]( + httpClient, + baseURL+BackrestPruneProcedure, + connect.WithSchema(backrestPruneMethodDescriptor), + connect.WithClientOptions(opts...), + ), + forget: connect.NewClient[types.StringValue, emptypb.Empty]( + httpClient, + baseURL+BackrestForgetProcedure, + connect.WithSchema(backrestForgetMethodDescriptor), + connect.WithClientOptions(opts...), + ), + restore: connect.NewClient[v1.RestoreSnapshotRequest, emptypb.Empty]( + httpClient, + baseURL+BackrestRestoreProcedure, + connect.WithSchema(backrestRestoreMethodDescriptor), + connect.WithClientOptions(opts...), + ), + unlock: connect.NewClient[types.StringValue, emptypb.Empty]( + httpClient, + baseURL+BackrestUnlockProcedure, + connect.WithSchema(backrestUnlockMethodDescriptor), + connect.WithClientOptions(opts...), + ), + cancel: connect.NewClient[types.Int64Value, emptypb.Empty]( + httpClient, + baseURL+BackrestCancelProcedure, + connect.WithSchema(backrestCancelMethodDescriptor), + connect.WithClientOptions(opts...), + ), + clearHistory: connect.NewClient[v1.ClearHistoryRequest, emptypb.Empty]( + httpClient, + baseURL+BackrestClearHistoryProcedure, + connect.WithSchema(backrestClearHistoryMethodDescriptor), + connect.WithClientOptions(opts...), + ), + pathAutocomplete: connect.NewClient[types.StringValue, types.StringList]( + httpClient, + baseURL+BackrestPathAutocompleteProcedure, + connect.WithSchema(backrestPathAutocompleteMethodDescriptor), + connect.WithClientOptions(opts...), + ), + } +} + +// backrestClient implements BackrestClient. +type backrestClient struct { + getConfig *connect.Client[emptypb.Empty, v1.Config] + setConfig *connect.Client[v1.Config, v1.Config] + addRepo *connect.Client[v1.Repo, v1.Config] + getOperationEvents *connect.Client[emptypb.Empty, v1.OperationEvent] + getOperations *connect.Client[v1.GetOperationsRequest, v1.OperationList] + listSnapshots *connect.Client[v1.ListSnapshotsRequest, v1.ResticSnapshotList] + listSnapshotFiles *connect.Client[v1.ListSnapshotFilesRequest, v1.ListSnapshotFilesResponse] + backup *connect.Client[types.StringValue, emptypb.Empty] + prune *connect.Client[types.StringValue, emptypb.Empty] + forget *connect.Client[types.StringValue, emptypb.Empty] + restore *connect.Client[v1.RestoreSnapshotRequest, emptypb.Empty] + unlock *connect.Client[types.StringValue, emptypb.Empty] + cancel *connect.Client[types.Int64Value, emptypb.Empty] + clearHistory *connect.Client[v1.ClearHistoryRequest, emptypb.Empty] + pathAutocomplete *connect.Client[types.StringValue, types.StringList] +} + +// GetConfig calls v1.Backrest.GetConfig. +func (c *backrestClient) GetConfig(ctx context.Context, req *connect.Request[emptypb.Empty]) (*connect.Response[v1.Config], error) { + return c.getConfig.CallUnary(ctx, req) +} + +// SetConfig calls v1.Backrest.SetConfig. +func (c *backrestClient) SetConfig(ctx context.Context, req *connect.Request[v1.Config]) (*connect.Response[v1.Config], error) { + return c.setConfig.CallUnary(ctx, req) +} + +// AddRepo calls v1.Backrest.AddRepo. +func (c *backrestClient) AddRepo(ctx context.Context, req *connect.Request[v1.Repo]) (*connect.Response[v1.Config], error) { + return c.addRepo.CallUnary(ctx, req) +} + +// GetOperationEvents calls v1.Backrest.GetOperationEvents. +func (c *backrestClient) GetOperationEvents(ctx context.Context, req *connect.Request[emptypb.Empty]) (*connect.ServerStreamForClient[v1.OperationEvent], error) { + return c.getOperationEvents.CallServerStream(ctx, req) +} + +// GetOperations calls v1.Backrest.GetOperations. +func (c *backrestClient) GetOperations(ctx context.Context, req *connect.Request[v1.GetOperationsRequest]) (*connect.Response[v1.OperationList], error) { + return c.getOperations.CallUnary(ctx, req) +} + +// ListSnapshots calls v1.Backrest.ListSnapshots. +func (c *backrestClient) ListSnapshots(ctx context.Context, req *connect.Request[v1.ListSnapshotsRequest]) (*connect.Response[v1.ResticSnapshotList], error) { + return c.listSnapshots.CallUnary(ctx, req) +} + +// ListSnapshotFiles calls v1.Backrest.ListSnapshotFiles. +func (c *backrestClient) ListSnapshotFiles(ctx context.Context, req *connect.Request[v1.ListSnapshotFilesRequest]) (*connect.Response[v1.ListSnapshotFilesResponse], error) { + return c.listSnapshotFiles.CallUnary(ctx, req) +} + +// Backup calls v1.Backrest.Backup. +func (c *backrestClient) Backup(ctx context.Context, req *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) { + return c.backup.CallUnary(ctx, req) +} + +// Prune calls v1.Backrest.Prune. +func (c *backrestClient) Prune(ctx context.Context, req *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) { + return c.prune.CallUnary(ctx, req) +} + +// Forget calls v1.Backrest.Forget. +func (c *backrestClient) Forget(ctx context.Context, req *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) { + return c.forget.CallUnary(ctx, req) +} + +// Restore calls v1.Backrest.Restore. +func (c *backrestClient) Restore(ctx context.Context, req *connect.Request[v1.RestoreSnapshotRequest]) (*connect.Response[emptypb.Empty], error) { + return c.restore.CallUnary(ctx, req) +} + +// Unlock calls v1.Backrest.Unlock. +func (c *backrestClient) Unlock(ctx context.Context, req *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) { + return c.unlock.CallUnary(ctx, req) +} + +// Cancel calls v1.Backrest.Cancel. +func (c *backrestClient) Cancel(ctx context.Context, req *connect.Request[types.Int64Value]) (*connect.Response[emptypb.Empty], error) { + return c.cancel.CallUnary(ctx, req) +} + +// ClearHistory calls v1.Backrest.ClearHistory. +func (c *backrestClient) ClearHistory(ctx context.Context, req *connect.Request[v1.ClearHistoryRequest]) (*connect.Response[emptypb.Empty], error) { + return c.clearHistory.CallUnary(ctx, req) +} + +// PathAutocomplete calls v1.Backrest.PathAutocomplete. +func (c *backrestClient) PathAutocomplete(ctx context.Context, req *connect.Request[types.StringValue]) (*connect.Response[types.StringList], error) { + return c.pathAutocomplete.CallUnary(ctx, req) +} + +// BackrestHandler is an implementation of the v1.Backrest service. +type BackrestHandler interface { + GetConfig(context.Context, *connect.Request[emptypb.Empty]) (*connect.Response[v1.Config], error) + SetConfig(context.Context, *connect.Request[v1.Config]) (*connect.Response[v1.Config], error) + AddRepo(context.Context, *connect.Request[v1.Repo]) (*connect.Response[v1.Config], error) + GetOperationEvents(context.Context, *connect.Request[emptypb.Empty], *connect.ServerStream[v1.OperationEvent]) error + GetOperations(context.Context, *connect.Request[v1.GetOperationsRequest]) (*connect.Response[v1.OperationList], error) + ListSnapshots(context.Context, *connect.Request[v1.ListSnapshotsRequest]) (*connect.Response[v1.ResticSnapshotList], error) + ListSnapshotFiles(context.Context, *connect.Request[v1.ListSnapshotFilesRequest]) (*connect.Response[v1.ListSnapshotFilesResponse], error) + // Backup schedules a backup operation. It accepts a plan id and returns empty if the task is enqueued. + Backup(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) + // Prune schedules a prune operation. + Prune(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) + // Forget schedules a forget operation. + Forget(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) + // Restore schedules a restore operation. + Restore(context.Context, *connect.Request[v1.RestoreSnapshotRequest]) (*connect.Response[emptypb.Empty], error) + // Unlock synchronously attempts to unlock the repo. Will block if other operations are in progress. + Unlock(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) + // Cancel attempts to cancel a task with the given operation ID. Not guaranteed to succeed. + Cancel(context.Context, *connect.Request[types.Int64Value]) (*connect.Response[emptypb.Empty], error) + ClearHistory(context.Context, *connect.Request[v1.ClearHistoryRequest]) (*connect.Response[emptypb.Empty], error) + // PathAutocomplete provides path autocompletion options for a given filesystem path. + PathAutocomplete(context.Context, *connect.Request[types.StringValue]) (*connect.Response[types.StringList], error) +} + +// NewBackrestHandler builds an HTTP handler from the service implementation. It returns the path on +// which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewBackrestHandler(svc BackrestHandler, opts ...connect.HandlerOption) (string, http.Handler) { + backrestGetConfigHandler := connect.NewUnaryHandler( + BackrestGetConfigProcedure, + svc.GetConfig, + connect.WithSchema(backrestGetConfigMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + backrestSetConfigHandler := connect.NewUnaryHandler( + BackrestSetConfigProcedure, + svc.SetConfig, + connect.WithSchema(backrestSetConfigMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + backrestAddRepoHandler := connect.NewUnaryHandler( + BackrestAddRepoProcedure, + svc.AddRepo, + connect.WithSchema(backrestAddRepoMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + backrestGetOperationEventsHandler := connect.NewServerStreamHandler( + BackrestGetOperationEventsProcedure, + svc.GetOperationEvents, + connect.WithSchema(backrestGetOperationEventsMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + backrestGetOperationsHandler := connect.NewUnaryHandler( + BackrestGetOperationsProcedure, + svc.GetOperations, + connect.WithSchema(backrestGetOperationsMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + backrestListSnapshotsHandler := connect.NewUnaryHandler( + BackrestListSnapshotsProcedure, + svc.ListSnapshots, + connect.WithSchema(backrestListSnapshotsMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + backrestListSnapshotFilesHandler := connect.NewUnaryHandler( + BackrestListSnapshotFilesProcedure, + svc.ListSnapshotFiles, + connect.WithSchema(backrestListSnapshotFilesMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + backrestBackupHandler := connect.NewUnaryHandler( + BackrestBackupProcedure, + svc.Backup, + connect.WithSchema(backrestBackupMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + backrestPruneHandler := connect.NewUnaryHandler( + BackrestPruneProcedure, + svc.Prune, + connect.WithSchema(backrestPruneMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + backrestForgetHandler := connect.NewUnaryHandler( + BackrestForgetProcedure, + svc.Forget, + connect.WithSchema(backrestForgetMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + backrestRestoreHandler := connect.NewUnaryHandler( + BackrestRestoreProcedure, + svc.Restore, + connect.WithSchema(backrestRestoreMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + backrestUnlockHandler := connect.NewUnaryHandler( + BackrestUnlockProcedure, + svc.Unlock, + connect.WithSchema(backrestUnlockMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + backrestCancelHandler := connect.NewUnaryHandler( + BackrestCancelProcedure, + svc.Cancel, + connect.WithSchema(backrestCancelMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + backrestClearHistoryHandler := connect.NewUnaryHandler( + BackrestClearHistoryProcedure, + svc.ClearHistory, + connect.WithSchema(backrestClearHistoryMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + backrestPathAutocompleteHandler := connect.NewUnaryHandler( + BackrestPathAutocompleteProcedure, + svc.PathAutocomplete, + connect.WithSchema(backrestPathAutocompleteMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + return "/v1.Backrest/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case BackrestGetConfigProcedure: + backrestGetConfigHandler.ServeHTTP(w, r) + case BackrestSetConfigProcedure: + backrestSetConfigHandler.ServeHTTP(w, r) + case BackrestAddRepoProcedure: + backrestAddRepoHandler.ServeHTTP(w, r) + case BackrestGetOperationEventsProcedure: + backrestGetOperationEventsHandler.ServeHTTP(w, r) + case BackrestGetOperationsProcedure: + backrestGetOperationsHandler.ServeHTTP(w, r) + case BackrestListSnapshotsProcedure: + backrestListSnapshotsHandler.ServeHTTP(w, r) + case BackrestListSnapshotFilesProcedure: + backrestListSnapshotFilesHandler.ServeHTTP(w, r) + case BackrestBackupProcedure: + backrestBackupHandler.ServeHTTP(w, r) + case BackrestPruneProcedure: + backrestPruneHandler.ServeHTTP(w, r) + case BackrestForgetProcedure: + backrestForgetHandler.ServeHTTP(w, r) + case BackrestRestoreProcedure: + backrestRestoreHandler.ServeHTTP(w, r) + case BackrestUnlockProcedure: + backrestUnlockHandler.ServeHTTP(w, r) + case BackrestCancelProcedure: + backrestCancelHandler.ServeHTTP(w, r) + case BackrestClearHistoryProcedure: + backrestClearHistoryHandler.ServeHTTP(w, r) + case BackrestPathAutocompleteProcedure: + backrestPathAutocompleteHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedBackrestHandler returns CodeUnimplemented from all methods. +type UnimplementedBackrestHandler struct{} + +func (UnimplementedBackrestHandler) GetConfig(context.Context, *connect.Request[emptypb.Empty]) (*connect.Response[v1.Config], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.GetConfig is not implemented")) +} + +func (UnimplementedBackrestHandler) SetConfig(context.Context, *connect.Request[v1.Config]) (*connect.Response[v1.Config], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.SetConfig is not implemented")) +} + +func (UnimplementedBackrestHandler) AddRepo(context.Context, *connect.Request[v1.Repo]) (*connect.Response[v1.Config], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.AddRepo is not implemented")) +} + +func (UnimplementedBackrestHandler) GetOperationEvents(context.Context, *connect.Request[emptypb.Empty], *connect.ServerStream[v1.OperationEvent]) error { + return connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.GetOperationEvents is not implemented")) +} + +func (UnimplementedBackrestHandler) GetOperations(context.Context, *connect.Request[v1.GetOperationsRequest]) (*connect.Response[v1.OperationList], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.GetOperations is not implemented")) +} + +func (UnimplementedBackrestHandler) ListSnapshots(context.Context, *connect.Request[v1.ListSnapshotsRequest]) (*connect.Response[v1.ResticSnapshotList], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.ListSnapshots is not implemented")) +} + +func (UnimplementedBackrestHandler) ListSnapshotFiles(context.Context, *connect.Request[v1.ListSnapshotFilesRequest]) (*connect.Response[v1.ListSnapshotFilesResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.ListSnapshotFiles is not implemented")) +} + +func (UnimplementedBackrestHandler) Backup(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.Backup is not implemented")) +} + +func (UnimplementedBackrestHandler) Prune(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.Prune is not implemented")) +} + +func (UnimplementedBackrestHandler) Forget(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.Forget is not implemented")) +} + +func (UnimplementedBackrestHandler) Restore(context.Context, *connect.Request[v1.RestoreSnapshotRequest]) (*connect.Response[emptypb.Empty], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.Restore is not implemented")) +} + +func (UnimplementedBackrestHandler) Unlock(context.Context, *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.Unlock is not implemented")) +} + +func (UnimplementedBackrestHandler) Cancel(context.Context, *connect.Request[types.Int64Value]) (*connect.Response[emptypb.Empty], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.Cancel is not implemented")) +} + +func (UnimplementedBackrestHandler) ClearHistory(context.Context, *connect.Request[v1.ClearHistoryRequest]) (*connect.Response[emptypb.Empty], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.ClearHistory is not implemented")) +} + +func (UnimplementedBackrestHandler) PathAutocomplete(context.Context, *connect.Request[types.StringValue]) (*connect.Response[types.StringList], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("v1.Backrest.PathAutocomplete is not implemented")) +} diff --git a/go.mod b/go.mod index eefa605d..3faaeebe 100644 --- a/go.mod +++ b/go.mod @@ -12,12 +12,14 @@ require ( github.com/natefinch/atomic v1.0.1 go.etcd.io/bbolt v1.3.8 go.uber.org/zap v1.26.0 - google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4 - google.golang.org/grpc v1.59.0 - google.golang.org/protobuf v1.31.0 + golang.org/x/crypto v0.17.0 + google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 + google.golang.org/grpc v1.60.1 + google.golang.org/protobuf v1.32.0 ) require ( + connectrpc.com/connect v1.14.0 // indirect github.com/daaku/go.zipexe v1.0.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -26,6 +28,6 @@ require ( golang.org/x/net v0.19.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto v0.0.0-20231127180814-3a041ad873d4 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 // indirect + google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect ) diff --git a/go.sum b/go.sum index d0b912de..b7d58be6 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +connectrpc.com/connect v1.14.0 h1:PDS+J7uoz5Oui2VEOMcfz6Qft7opQM9hPiKvtGC01pA= +connectrpc.com/connect v1.14.0/go.mod h1:uoAq5bmhhn43TwhaKdGKN/bZcGtzPW1v+ngDTn5u+8s= github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= github.com/GeertJohan/go.rice v1.0.3 h1:k5viR+xGtIhF61125vCE1cmJ5957RQGXG6dmbaWZSmI= github.com/GeertJohan/go.rice v1.0.3/go.mod h1:XVdrU4pW00M4ikZed5q56tPf1v2KwnIKeIdc9CBYNt4= @@ -46,6 +48,8 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -57,15 +61,25 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto v0.0.0-20231127180814-3a041ad873d4 h1:W12Pwm4urIbRdGhMEg2NM9O3TWKjNcxQhs46V0ypf/k= google.golang.org/genproto v0.0.0-20231127180814-3a041ad873d4/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4 h1:ZcOkrmX74HbKFYnpPY8Qsw93fC29TbJXspYKaBkSXDQ= google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4/go.mod h1:k2dtGpRrbsSyKcNPKKI5sstZkrNCZwpU/ns96JoHbGg= +google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 h1:s1w3X6gQxwrLEpxnLd/qXTVLgQE2yXwaOaoa6IlY/+o= +google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0/go.mod h1:CAny0tYF+0/9rmDB9fahA9YLzX3+AEVl1qXbv5hhj6c= google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 h1:DC7wcm+i+P1rN3Ff07vL+OndGg5OhNddHyTA+ocPqYE= google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4/go.mod h1:eJVxU6o+4G1PSczBr85xmyvSNYAKvAYgkub40YGomFM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 h1:/jFB8jK5R3Sq3i/lmeZO0cATSzFfZaJq1J2Euan3XKU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/api/api.go b/internal/api/api.go deleted file mode 100644 index 119e4463..00000000 --- a/internal/api/api.go +++ /dev/null @@ -1,112 +0,0 @@ -package api - -import ( - "context" - "fmt" - "net" - "net/http" - "os" - "path/filepath" - - v1 "github.com/garethgeorge/backrest/gen/go/v1" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "go.uber.org/zap" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" -) - -func loggingFunc(l *zap.Logger) logging.Logger { - return logging.LoggerFunc(func(ctx context.Context, lvl logging.Level, msg string, fields ...any) { - f := make([]zap.Field, 0, len(fields)/2) - - for i := 0; i < len(fields); i += 2 { - key := fields[i] - value := fields[i+1] - - switch v := value.(type) { - case string: - f = append(f, zap.String(key.(string), v)) - case int: - f = append(f, zap.Int(key.(string), v)) - case bool: - f = append(f, zap.Bool(key.(string), v)) - default: - f = append(f, zap.Any(key.(string), v)) - } - } - - logger := l.WithOptions(zap.AddCallerSkip(1)).With(f...) - - switch lvl { - case logging.LevelDebug: - logger.Debug(msg) - case logging.LevelInfo: - logger.Debug(msg) - case logging.LevelWarn: - logger.Warn(msg) - case logging.LevelError: - logger.Error(msg) - default: - panic(fmt.Sprintf("unknown level %v", lvl)) - } - }) -} - -func serveGRPC(ctx context.Context, socket string, server *Server) error { - lis, err := net.Listen("unix", socket) - if err != nil { - return fmt.Errorf("failed to listen: %w", err) - } - - logger := zap.L() - grpcServer := grpc.NewServer( - grpc.ChainUnaryInterceptor( - logging.UnaryServerInterceptor(loggingFunc(logger)), - ), - grpc.ChainStreamInterceptor( - logging.StreamServerInterceptor(loggingFunc(logger)), - ), - ) - v1.RegisterBackrestServer(grpcServer, server) - go func() { - <-ctx.Done() - grpcServer.GracefulStop() - }() - err = grpcServer.Serve(lis) - if err != nil { - return fmt.Errorf("grpc serving error: %w", err) - } - return nil -} - -func serveHTTPHandlers(ctx context.Context, server *Server, mux *runtime.ServeMux) error { - tmpDir, err := os.MkdirTemp("", "backrest") - if err != nil { - return fmt.Errorf("failed to create temp dir for unix domain socket: %w", err) - } - defer func() { - os.RemoveAll(tmpDir) - }() - - socket := filepath.Join(tmpDir, "backrest.sock") - - opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())} - err = v1.RegisterBackrestHandlerFromEndpoint(ctx, mux, fmt.Sprintf("unix:%v", socket), opts) - if err != nil { - return fmt.Errorf("failed to register gateway: %w", err) - } - - if err := serveGRPC(ctx, socket, server); err != nil { - return err - } - - return nil -} - -// Handler returns an http.Handler serving the API, cancel the context to cleanly shut down the server. -func ServeAPI(ctx context.Context, server *Server, mux *http.ServeMux) error { - apiMux := runtime.NewServeMux() - mux.Handle("/api/", http.StripPrefix("/api", apiMux)) - return serveHTTPHandlers(ctx, server, apiMux) -} diff --git a/internal/api/auth.go b/internal/api/auth.go new file mode 100644 index 00000000..8caa7cac --- /dev/null +++ b/internal/api/auth.go @@ -0,0 +1,48 @@ +package api + +import ( + "encoding/base64" + + v1 "github.com/garethgeorge/backrest/gen/go/v1" + "golang.org/x/crypto/bcrypt" +) + +type User v1.User + +func (u *User) CheckPassword(password string) bool { + switch pw := u.Password.(type) { + case *v1.User_PasswordBcrypt: + pwHash, err := base64.StdEncoding.DecodeString(pw.PasswordBcrypt) + if err != nil { + return false + } + return bcrypt.CompareHashAndPassword(pwHash, []byte(password)) == nil + default: + return false + } +} + +type Authenticator struct { + users map[string]*User +} + +func NewAuthenticator(users []*v1.User) *Authenticator { + auth := &Authenticator{ + users: make(map[string]*User), + } + for _, user := range users { + auth.users[user.Name] = (*User)(user) + } + return auth +} + +func (a *Authenticator) Authenticate(username, password string) (*User, bool) { + user, ok := a.users[username] + if !ok { + return nil, false + } + if !user.CheckPassword(password) { + return nil, false + } + return user, true +} diff --git a/internal/api/server.go b/internal/api/server.go index 61b2d117..8a62f615 100644 --- a/internal/api/server.go +++ b/internal/api/server.go @@ -8,8 +8,10 @@ import ( "path" "time" + "connectrpc.com/connect" "github.com/garethgeorge/backrest/gen/go/types" v1 "github.com/garethgeorge/backrest/gen/go/v1" + "github.com/garethgeorge/backrest/gen/go/v1/v1connect" "github.com/garethgeorge/backrest/internal/config" "github.com/garethgeorge/backrest/internal/oplog" "github.com/garethgeorge/backrest/internal/oplog/indexutil" @@ -23,13 +25,13 @@ import ( ) type Server struct { - *v1.UnimplementedBackrestServer + v1connect.UnimplementedBackrestHandler config config.ConfigStore orchestrator *orchestrator.Orchestrator oplog *oplog.OpLog } -var _ v1.BackrestServer = &Server{} +var _ v1connect.BackrestHandler = &Server{} func NewServer(config config.ConfigStore, orchestrator *orchestrator.Orchestrator, oplog *oplog.OpLog) *Server { s := &Server{ @@ -42,24 +44,28 @@ func NewServer(config config.ConfigStore, orchestrator *orchestrator.Orchestrato } // GetConfig implements GET /v1/config -func (s *Server) GetConfig(ctx context.Context, empty *emptypb.Empty) (*v1.Config, error) { - return s.config.Get() +func (s *Server) GetConfig(ctx context.Context, req *connect.Request[emptypb.Empty]) (*connect.Response[v1.Config], error) { + config, err := s.config.Get() + if err != nil { + return nil, fmt.Errorf("failed to get config: %w", err) + } + return connect.NewResponse(config), nil } // SetConfig implements POST /v1/config -func (s *Server) SetConfig(ctx context.Context, c *v1.Config) (*v1.Config, error) { +func (s *Server) SetConfig(ctx context.Context, req *connect.Request[v1.Config]) (*connect.Response[v1.Config], error) { existing, err := s.config.Get() if err != nil { return nil, fmt.Errorf("failed to check current config: %w", err) } // Compare and increment modno - if existing.Modno != c.Modno { + if existing.Modno != req.Msg.Modno { return nil, errors.New("config modno mismatch, reload and try again") } - c.Modno += 1 + req.Msg.Modno += 1 - if err := s.config.Update(c); err != nil { + if err := s.config.Update(req.Msg); err != nil { return nil, fmt.Errorf("failed to update config: %w", err) } @@ -67,19 +73,21 @@ func (s *Server) SetConfig(ctx context.Context, c *v1.Config) (*v1.Config, error if err != nil { return nil, fmt.Errorf("failed to get newly set config: %w", err) } - s.orchestrator.ApplyConfig(newConfig) - return newConfig, nil + if err := s.orchestrator.ApplyConfig(newConfig); err != nil { + return nil, fmt.Errorf("failed to apply config: %w", err) + } + return connect.NewResponse(newConfig), nil } // AddRepo implements POST /v1/config/repo, it includes validation that the repo can be initialized. -func (s *Server) AddRepo(ctx context.Context, repo *v1.Repo) (*v1.Config, error) { +func (s *Server) AddRepo(ctx context.Context, req *connect.Request[v1.Repo]) (*connect.Response[v1.Config], error) { c, err := s.config.Get() if err != nil { return nil, fmt.Errorf("failed to get config: %w", err) } c = proto.Clone(c).(*v1.Config) - c.Repos = append(c.Repos, repo) + c.Repos = append(c.Repos, req.Msg) if err := config.ValidateConfig(c); err != nil { return nil, fmt.Errorf("validation error: %w", err) @@ -90,7 +98,7 @@ func (s *Server) AddRepo(ctx context.Context, repo *v1.Repo) (*v1.Config, error) return nil, fmt.Errorf("failed to find or install restic binary: %w", err) } - r := restic.NewRepo(bin, repo) + r := restic.NewRepo(bin, req.Msg) // use background context such that the init op can try to complete even if the connection is closed. if err := r.Init(context.Background()); err != nil { return nil, fmt.Errorf("failed to init repo: %w", err) @@ -103,11 +111,12 @@ func (s *Server) AddRepo(ctx context.Context, repo *v1.Repo) (*v1.Config, error) s.orchestrator.ApplyConfig(c) - return c, nil + return connect.NewResponse(c), nil } // ListSnapshots implements POST /v1/snapshots -func (s *Server) ListSnapshots(ctx context.Context, query *v1.ListSnapshotsRequest) (*v1.ResticSnapshotList, error) { +func (s *Server) ListSnapshots(ctx context.Context, req *connect.Request[v1.ListSnapshotsRequest]) (*connect.Response[v1.ResticSnapshotList], error) { + query := req.Msg repo, err := s.orchestrator.GetRepo(query.RepoId) if err != nil { return nil, fmt.Errorf("failed to get repo: %w", err) @@ -135,12 +144,13 @@ func (s *Server) ListSnapshots(ctx context.Context, query *v1.ListSnapshotsReque rs = append(rs, protoutil.SnapshotToProto(snapshot)) } - return &v1.ResticSnapshotList{ + return connect.NewResponse(&v1.ResticSnapshotList{ Snapshots: rs, - }, nil + }), nil } -func (s *Server) ListSnapshotFiles(ctx context.Context, query *v1.ListSnapshotFilesRequest) (*v1.ListSnapshotFilesResponse, error) { +func (s *Server) ListSnapshotFiles(ctx context.Context, req *connect.Request[v1.ListSnapshotFilesRequest]) (*connect.Response[v1.ListSnapshotFilesResponse], error) { + query := req.Msg repo, err := s.orchestrator.GetRepo(query.RepoId) if err != nil { return nil, fmt.Errorf("failed to get repo: %w", err) @@ -151,14 +161,14 @@ func (s *Server) ListSnapshotFiles(ctx context.Context, query *v1.ListSnapshotFi return nil, fmt.Errorf("failed to list snapshot files: %w", err) } - return &v1.ListSnapshotFilesResponse{ + return connect.NewResponse(&v1.ListSnapshotFilesResponse{ Path: query.Path, Entries: entries, - }, nil + }), nil } // GetOperationEvents implements GET /v1/events/operations -func (s *Server) GetOperationEvents(_ *emptypb.Empty, stream v1.Backrest_GetOperationEventsServer) error { +func (s *Server) GetOperationEvents(ctx context.Context, req *connect.Request[emptypb.Empty], resp *connect.ServerStream[v1.OperationEvent]) error { errorChan := make(chan error) defer close(errorChan) callback := func(oldOp *v1.Operation, newOp *v1.Operation) { @@ -184,7 +194,7 @@ func (s *Server) GetOperationEvents(_ *emptypb.Empty, stream v1.Backrest_GetOper } go func() { - if err := stream.Send(event); err != nil { + if err := resp.Send(event); err != nil { errorChan <- fmt.Errorf("failed to send event: %w", err) } }() @@ -192,18 +202,18 @@ func (s *Server) GetOperationEvents(_ *emptypb.Empty, stream v1.Backrest_GetOper s.oplog.Subscribe(&callback) defer s.oplog.Unsubscribe(&callback) select { - case <-stream.Context().Done(): + case <-ctx.Done(): return nil case err := <-errorChan: return err } } -func (s *Server) GetOperations(ctx context.Context, req *v1.GetOperationsRequest) (*v1.OperationList, error) { +func (s *Server) GetOperations(ctx context.Context, req *connect.Request[v1.GetOperationsRequest]) (*connect.Response[v1.OperationList], error) { idCollector := indexutil.CollectAll() - if req.LastN != 0 { - idCollector = indexutil.CollectLastN(int(req.LastN)) + if req.Msg.LastN != 0 { + idCollector = indexutil.CollectLastN(int(req.Msg.LastN)) } var err error @@ -212,17 +222,17 @@ func (s *Server) GetOperations(ctx context.Context, req *v1.GetOperationsRequest ops = append(ops, op) return nil } - if req.RepoId != "" && req.PlanId != "" { + if req.Msg.RepoId != "" && req.Msg.PlanId != "" { return nil, errors.New("cannot specify both repoId and planId") - } else if req.PlanId != "" { - err = s.oplog.ForEachByPlan(req.PlanId, idCollector, opCollector) - } else if req.RepoId != "" { - err = s.oplog.ForEachByRepo(req.RepoId, idCollector, opCollector) - } else if req.SnapshotId != "" { - err = s.oplog.ForEachBySnapshotId(req.SnapshotId, idCollector, opCollector) - } else if len(req.Ids) > 0 { - ops = make([]*v1.Operation, 0, len(req.Ids)) - for i, id := range req.Ids { + } else if req.Msg.PlanId != "" { + err = s.oplog.ForEachByPlan(req.Msg.PlanId, idCollector, opCollector) + } else if req.Msg.RepoId != "" { + err = s.oplog.ForEachByRepo(req.Msg.RepoId, idCollector, opCollector) + } else if req.Msg.SnapshotId != "" { + err = s.oplog.ForEachBySnapshotId(req.Msg.SnapshotId, idCollector, opCollector) + } else if len(req.Msg.Ids) > 0 { + ops = make([]*v1.Operation, 0, len(req.Msg.Ids)) + for i, id := range req.Msg.Ids { op, err := s.oplog.Get(id) if err != nil { return nil, fmt.Errorf("failed to get operation %d: %w", i, err) @@ -236,24 +246,24 @@ func (s *Server) GetOperations(ctx context.Context, req *v1.GetOperationsRequest return nil, fmt.Errorf("failed to get operations: %w", err) } - return &v1.OperationList{ + return connect.NewResponse(&v1.OperationList{ Operations: ops, - }, nil + }), nil } -func (s *Server) Backup(ctx context.Context, req *types.StringValue) (*emptypb.Empty, error) { - plan, err := s.orchestrator.GetPlan(req.Value) +func (s *Server) Backup(ctx context.Context, req *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) { + plan, err := s.orchestrator.GetPlan(req.Msg.Value) if err != nil { - return nil, fmt.Errorf("failed to get plan %q: %w", req.Value, err) + return nil, fmt.Errorf("failed to get plan %q: %w", req.Msg.Value, err) } s.orchestrator.ScheduleTask(orchestrator.NewOneofBackupTask(s.orchestrator, plan, time.Now()), orchestrator.TaskPriorityInteractive) - return &emptypb.Empty{}, nil + return connect.NewResponse(&emptypb.Empty{}), nil } -func (s *Server) Forget(ctx context.Context, req *types.StringValue) (*emptypb.Empty, error) { - plan, err := s.orchestrator.GetPlan(req.Value) +func (s *Server) Forget(ctx context.Context, req *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) { + plan, err := s.orchestrator.GetPlan(req.Msg.Value) if err != nil { - return nil, fmt.Errorf("failed to get plan %q: %w", req.Value, err) + return nil, fmt.Errorf("failed to get plan %q: %w", req.Msg.Value, err) } at := time.Now() @@ -261,87 +271,87 @@ func (s *Server) Forget(ctx context.Context, req *types.StringValue) (*emptypb.E s.orchestrator.ScheduleTask(orchestrator.NewOneofForgetTask(s.orchestrator, plan, "", at), orchestrator.TaskPriorityInteractive+orchestrator.TaskPriorityForget) s.orchestrator.ScheduleTask(orchestrator.NewOneofForgetTask(s.orchestrator, plan, "", at), orchestrator.TaskPriorityInteractive+orchestrator.TaskPriorityIndexSnapshots) - return &emptypb.Empty{}, nil + return connect.NewResponse(&emptypb.Empty{}), nil } -func (s *Server) Prune(ctx context.Context, req *types.StringValue) (*emptypb.Empty, error) { - plan, err := s.orchestrator.GetPlan(req.Value) +func (s *Server) Prune(ctx context.Context, req *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) { + plan, err := s.orchestrator.GetPlan(req.Msg.Value) if err != nil { - return nil, fmt.Errorf("failed to get plan %q: %w", req.Value, err) + return nil, fmt.Errorf("failed to get plan %q: %w", req.Msg.Value, err) } at := time.Now() - s.orchestrator.ScheduleTask(orchestrator.NewOneofPruneTask(s.orchestrator, plan, "", at, true), orchestrator.TaskPriorityInteractive+orchestrator.TaskPriorityPrune) - return &emptypb.Empty{}, nil + return connect.NewResponse(&emptypb.Empty{}), nil } -func (s *Server) Restore(ctx context.Context, req *v1.RestoreSnapshotRequest) (*emptypb.Empty, error) { - _, err := s.orchestrator.GetRepo(req.RepoId) +func (s *Server) Restore(ctx context.Context, req *connect.Request[v1.RestoreSnapshotRequest]) (*connect.Response[emptypb.Empty], error) { + _, err := s.orchestrator.GetRepo(req.Msg.RepoId) if err != nil { - return nil, fmt.Errorf("failed to get repo %q: %w", req.RepoId, err) + return nil, fmt.Errorf("failed to get repo %q: %w", req.Msg.RepoId, err) } - if req.Target == "" { - req.Target = path.Join(os.Getenv("HOME"), "Downloads") + if req.Msg.Target == "" { + req.Msg.Target = path.Join(os.Getenv("HOME"), "Downloads") } - target := path.Join(req.Target, fmt.Sprintf("restic-restore-%v", time.Now().Format("2006-01-02T15-04-05"))) + target := path.Join(req.Msg.Target, fmt.Sprintf("restic-restore-%v", time.Now().Format("2006-01-02T15-04-05"))) _, err = os.Stat(target) if !errors.Is(err, os.ErrNotExist) { - return nil, fmt.Errorf("restore target dir %q already exists", req.Target) + return nil, fmt.Errorf("restore target dir %q already exists", req.Msg.Target) } at := time.Now() s.orchestrator.ScheduleTask(orchestrator.NewOneofRestoreTask(s.orchestrator, orchestrator.RestoreTaskOpts{ - PlanId: req.PlanId, - RepoId: req.RepoId, - SnapshotId: req.SnapshotId, - Path: req.Path, + PlanId: req.Msg.PlanId, + RepoId: req.Msg.RepoId, + SnapshotId: req.Msg.SnapshotId, + Path: req.Msg.Path, Target: target, }, at), orchestrator.TaskPriorityInteractive+orchestrator.TaskPriorityDefault) - return &emptypb.Empty{}, nil + return connect.NewResponse(&emptypb.Empty{}), nil } -func (s *Server) Unlock(ctx context.Context, req *types.StringValue) (*emptypb.Empty, error) { - repo, err := s.orchestrator.GetRepo(req.Value) +func (s *Server) Unlock(ctx context.Context, req *connect.Request[types.StringValue]) (*connect.Response[emptypb.Empty], error) { + repo, err := s.orchestrator.GetRepo(req.Msg.Value) if err != nil { - return nil, fmt.Errorf("failed to get repo %q: %w", req.Value, err) + return nil, fmt.Errorf("failed to get repo %q: %w", req.Msg.Value, err) } if err := repo.Unlock(context.Background()); err != nil { - return nil, fmt.Errorf("failed to unlock repo %q: %w", req.Value, err) + return nil, fmt.Errorf("failed to unlock repo %q: %w", req.Msg.Value, err) } - return &emptypb.Empty{}, nil + return connect.NewResponse(&emptypb.Empty{}), nil } -func (s *Server) Cancel(ctx context.Context, req *types.Int64Value) (*emptypb.Empty, error) { - if err := s.orchestrator.CancelOperation(req.Value, v1.OperationStatus_STATUS_USER_CANCELLED); err != nil { +func (s *Server) Cancel(ctx context.Context, req *connect.Request[types.Int64Value]) (*connect.Response[emptypb.Empty], error) { + if err := s.orchestrator.CancelOperation(req.Msg.Value, v1.OperationStatus_STATUS_USER_CANCELLED); err != nil { return nil, err } - return &emptypb.Empty{}, nil + + return connect.NewResponse(&emptypb.Empty{}), nil } -func (s *Server) ClearHistory(ctx context.Context, req *v1.ClearHistoryRequest) (*emptypb.Empty, error) { +func (s *Server) ClearHistory(ctx context.Context, req *connect.Request[v1.ClearHistoryRequest]) (*connect.Response[emptypb.Empty], error) { var err error var ids []int64 opCollector := func(op *v1.Operation) error { - if !req.OnlyFailed || op.Status == v1.OperationStatus_STATUS_ERROR { + if !req.Msg.OnlyFailed || op.Status == v1.OperationStatus_STATUS_ERROR { ids = append(ids, op.Id) } return nil } - if req.RepoId != "" && req.PlanId != "" { + if req.Msg.RepoId != "" && req.Msg.PlanId != "" { return nil, errors.New("cannot specify both repoId and planId") - } else if req.PlanId != "" { - err = s.oplog.ForEachByPlan(req.PlanId, indexutil.CollectAll(), opCollector) - } else if req.RepoId != "" { - err = s.oplog.ForEachByRepo(req.RepoId, indexutil.CollectAll(), opCollector) + } else if req.Msg.PlanId != "" { + err = s.oplog.ForEachByPlan(req.Msg.PlanId, indexutil.CollectAll(), opCollector) + } else if req.Msg.RepoId != "" { + err = s.oplog.ForEachByRepo(req.Msg.RepoId, indexutil.CollectAll(), opCollector) } if err != nil { @@ -355,10 +365,10 @@ func (s *Server) ClearHistory(ctx context.Context, req *v1.ClearHistoryRequest) return nil, err } -func (s *Server) PathAutocomplete(ctx context.Context, path *types.StringValue) (*types.StringList, error) { - ents, err := os.ReadDir(path.Value) +func (s *Server) PathAutocomplete(ctx context.Context, path *connect.Request[types.StringValue]) (*connect.Response[types.StringList], error) { + ents, err := os.ReadDir(path.Msg.Value) if errors.Is(err, os.ErrNotExist) { - return &types.StringList{}, nil + return connect.NewResponse(&types.StringList{}), nil } else if err != nil { return nil, err } @@ -368,5 +378,5 @@ func (s *Server) PathAutocomplete(ctx context.Context, path *types.StringValue) paths = append(paths, ent.Name()) } - return &types.StringList{Values: paths}, nil + return connect.NewResponse(&types.StringList{Values: paths}), nil } diff --git a/proto/buf.gen.yaml b/proto/buf.gen.yaml index 2b42b990..13fd92da 100644 --- a/proto/buf.gen.yaml +++ b/proto/buf.gen.yaml @@ -8,12 +8,15 @@ plugins: out: ../gen/go opt: - paths=source_relative - - plugin: grpc-gateway + - plugin: connect-go out: ../gen/go opt: - paths=source_relative - - generate_unbound_methods=true - - plugin: grpc-gateway-ts + - plugin: es out: ../webui/gen/ts - opt: - - paths=source_relative \ No newline at end of file + opt: + - target=ts + - plugin: connect-es + out: ../webui/gen/ts + opt: + - target=ts \ No newline at end of file diff --git a/proto/v1/config.proto b/proto/v1/config.proto index 72279066..06e4255f 100644 --- a/proto/v1/config.proto +++ b/proto/v1/config.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package v1; -option go_package = "github.com/garethgeorge/backrest/go/proto/v1"; +option go_package = "github.com/garethgeorge/backrest/gen/go/v1"; // Config is the top level config object for restic UI. message Config { @@ -14,6 +14,7 @@ message Config { repeated Repo repos = 3 [json_name="repos"]; repeated Plan plans = 4 [json_name="plans"]; + repeated User users = 5 [json_name="users"]; } message Repo { @@ -51,4 +52,11 @@ message PrunePolicy { int32 max_frequency_days = 1; // max frequency of prune runs in days. If 0, prune will be run on every backup. int32 max_unused_percent = 100; // max percentage of repo size that can be unused before prune is run. int32 max_unused_bytes = 101; // max number of bytes that can be unused before prune is run. +} + +message User { + string name = 1; + oneof password { + string password_bcrypt = 2; + } } \ No newline at end of file diff --git a/proto/v1/operations.proto b/proto/v1/operations.proto index c39bc0f7..bfb506ba 100644 --- a/proto/v1/operations.proto +++ b/proto/v1/operations.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package v1; -option go_package = "github.com/garethgeorge/backrest/go/proto/v1"; +option go_package = "github.com/garethgeorge/backrest/gen/go/v1"; import "v1/restic.proto"; import "v1/config.proto"; diff --git a/proto/v1/restic.proto b/proto/v1/restic.proto index 10f85fca..d949159b 100644 --- a/proto/v1/restic.proto +++ b/proto/v1/restic.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package v1; -option go_package = "github.com/garethgeorge/backrest/go/proto/v1"; +option go_package = "github.com/garethgeorge/backrest/gen/go/v1"; // ResticSnapshot represents a restic snapshot. message ResticSnapshot { diff --git a/proto/v1/service.proto b/proto/v1/service.proto index f6fdf13e..3aa8cffc 100644 --- a/proto/v1/service.proto +++ b/proto/v1/service.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package v1; -option go_package = "github.com/garethgeorge/backrest/go/proto/v1"; +option go_package = "github.com/garethgeorge/backrest/gen/go/v1"; import "v1/config.proto"; import "v1/restic.proto"; @@ -12,115 +12,42 @@ import "google/protobuf/empty.proto"; import "google/api/annotations.proto"; service Backrest { - rpc GetConfig (google.protobuf.Empty) returns (Config) { - option (google.api.http) = { - get: "/v1/config" - }; - } - - rpc SetConfig (Config) returns (Config) { - option (google.api.http) = { - post: "/v1/config" - body: "*" - }; - } - - rpc AddRepo (Repo) returns (Config) { - option (google.api.http) = { - post: "/v1/config/repo" - body: "*" - }; - } - - rpc GetOperationEvents (google.protobuf.Empty) returns (stream OperationEvent) { - option (google.api.http) = { - get: "/v1/events/operations" - }; - } - - rpc GetOperations (GetOperationsRequest) returns (OperationList) { - option (google.api.http) = { - post: "/v1/operations" - body: "*" - }; - } - - rpc ListSnapshots(ListSnapshotsRequest) returns (ResticSnapshotList) { - option (google.api.http) = { - post: "/v1/snapshots" - body: "*" - }; - } + rpc GetConfig (google.protobuf.Empty) returns (Config) {} + + rpc SetConfig (Config) returns (Config) {} + + rpc AddRepo (Repo) returns (Config) {} + + rpc GetOperationEvents (google.protobuf.Empty) returns (stream OperationEvent) {} + + rpc GetOperations (GetOperationsRequest) returns (OperationList) {} + + rpc ListSnapshots(ListSnapshotsRequest) returns (ResticSnapshotList) {} - rpc ListSnapshotFiles(ListSnapshotFilesRequest) returns (ListSnapshotFilesResponse) { - option (google.api.http) = { - post: "/v1/snapshots/files" - body: "*" - }; - } + rpc ListSnapshotFiles(ListSnapshotFilesRequest) returns (ListSnapshotFilesResponse) {} // Backup schedules a backup operation. It accepts a plan id and returns empty if the task is enqueued. - rpc Backup(types.StringValue) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/v1/cmd/backup" - body: "*" - }; - } + rpc Backup(types.StringValue) returns (google.protobuf.Empty) {} // Prune schedules a prune operation. - rpc Prune(types.StringValue) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/v1/cmd/prune" - body: "*" - }; - } + rpc Prune(types.StringValue) returns (google.protobuf.Empty) {} // Forget schedules a forget operation. - rpc Forget(types.StringValue) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/v1/cmd/forget" - body: "*" - }; - } + rpc Forget(types.StringValue) returns (google.protobuf.Empty) {} // Restore schedules a restore operation. - rpc Restore(RestoreSnapshotRequest) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/v1/cmd/restore" - body: "*" - }; - } + rpc Restore(RestoreSnapshotRequest) returns (google.protobuf.Empty) {} // Unlock synchronously attempts to unlock the repo. Will block if other operations are in progress. - rpc Unlock(types.StringValue) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/v1/cmd/unlock" - body: "*" - }; - } + rpc Unlock(types.StringValue) returns (google.protobuf.Empty) {} // Cancel attempts to cancel a task with the given operation ID. Not guaranteed to succeed. - rpc Cancel(types.Int64Value) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/v1/cmd/cancel" - body: "*" - }; - } - - rpc ClearHistory(ClearHistoryRequest) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/v1/cmd/clear_history" - body: "*" - }; - } + rpc Cancel(types.Int64Value) returns (google.protobuf.Empty) {} + + rpc ClearHistory(ClearHistoryRequest) returns (google.protobuf.Empty) {} // PathAutocomplete provides path autocompletion options for a given filesystem path. - rpc PathAutocomplete (types.StringValue) returns (types.StringList) { - option (google.api.http) = { - post: "/v1/autocomplete/path" - body: "*" - }; - } + rpc PathAutocomplete (types.StringValue) returns (types.StringList) {} } message ClearHistoryRequest { diff --git a/webui/gen/ts/fetch.pb.ts b/webui/gen/ts/fetch.pb.ts deleted file mode 100644 index 82736361..00000000 --- a/webui/gen/ts/fetch.pb.ts +++ /dev/null @@ -1,341 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck -/* -* This file is a generated Typescript file for GRPC Gateway, DO NOT MODIFY -*/ - -/** - * base64 encoder and decoder - * Copied and adapted from https://github.com/protobufjs/protobuf.js/blob/master/lib/base64/index.js - */ -// Base64 encoding table -const b64 = new Array(64); - -// Base64 decoding table -const s64 = new Array(123); - -// 65..90, 97..122, 48..57, 43, 47 -for (let i = 0; i < 64;) - s64[b64[i] = i < 26 ? i + 65 : i < 52 ? i + 71 : i < 62 ? i - 4 : i - 59 | 43] = i++; - -export function b64Encode(buffer: Uint8Array, start: number, end: number): string { - let parts: string[] = null; - const chunk = []; - let i = 0, // output index - j = 0, // goto index - t; // temporary - while (start < end) { - const b = buffer[start++]; - switch (j) { - case 0: - chunk[i++] = b64[b >> 2]; - t = (b & 3) << 4; - j = 1; - break; - case 1: - chunk[i++] = b64[t | b >> 4]; - t = (b & 15) << 2; - j = 2; - break; - case 2: - chunk[i++] = b64[t | b >> 6]; - chunk[i++] = b64[b & 63]; - j = 0; - break; - } - if (i > 8191) { - (parts || (parts = [])).push(String.fromCharCode.apply(String, chunk)); - i = 0; - } - } - if (j) { - chunk[i++] = b64[t]; - chunk[i++] = 61; - if (j === 1) - chunk[i++] = 61; - } - if (parts) { - if (i) - parts.push(String.fromCharCode.apply(String, chunk.slice(0, i))); - return parts.join(""); - } - return String.fromCharCode.apply(String, chunk.slice(0, i)); -} - -const invalidEncoding = "invalid encoding"; - -export function b64Decode(s: string): Uint8Array { - const buffer = []; - let offset = 0; - let j = 0, // goto index - t; // temporary - for (let i = 0; i < s.length;) { - let c = s.charCodeAt(i++); - if (c === 61 && j > 1) - break; - if ((c = s64[c]) === undefined) - throw Error(invalidEncoding); - switch (j) { - case 0: - t = c; - j = 1; - break; - case 1: - buffer[offset++] = t << 2 | (c & 48) >> 4; - t = c; - j = 2; - break; - case 2: - buffer[offset++] = (t & 15) << 4 | (c & 60) >> 2; - t = c; - j = 3; - break; - case 3: - buffer[offset++] = (t & 3) << 6 | c; - j = 0; - break; - } - } - if (j === 1) - throw Error(invalidEncoding); - return new Uint8Array(buffer); -} - -function b64Test(s: string): boolean { - return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(s); -} - -export interface InitReq extends RequestInit { - pathPrefix?: string -} - -export function replacer(key: any, value: any): any { - if(value && value.constructor === Uint8Array) { - return b64Encode(value, 0, value.length); - } - - return value; -} - -export function fetchReq(path: string, init?: InitReq): Promise { - const {pathPrefix, ...req} = init || {} - - const url = pathPrefix ? `${pathPrefix}${path}` : path - - return fetch(url, req).then(r => r.json().then((body: O) => { - if (!r.ok) { throw body; } - return body; - })) as Promise -} - -// NotifyStreamEntityArrival is a callback that will be called on streaming entity arrival -export type NotifyStreamEntityArrival = (resp: T) => void - -/** - * fetchStreamingRequest is able to handle grpc-gateway server side streaming call - * it takes NotifyStreamEntityArrival that lets users respond to entity arrival during the call - * all entities will be returned as an array after the call finishes. - **/ -export async function fetchStreamingRequest(path: string, callback?: NotifyStreamEntityArrival, init?: InitReq) { - const {pathPrefix, ...req} = init || {} - const url = pathPrefix ?`${pathPrefix}${path}` : path - const result = await fetch(url, req) - // needs to use the .ok to check the status of HTTP status code - // http other than 200 will not throw an error, instead the .ok will become false. - // see https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch# - if (!result.ok) { - const resp = await result.json() - const errMsg = resp.error && resp.error.message ? resp.error.message : "" - throw new Error(errMsg) - } - - if (!result.body) { - throw new Error("response doesnt have a body") - } - - await result.body - .pipeThrough(new TextDecoderStream()) - .pipeThrough(getNewLineDelimitedJSONDecodingStream()) - .pipeTo(getNotifyEntityArrivalSink((e: R) => { - if (callback) { - callback(e) - } - })) - - // wait for the streaming to finish and return the success respond - return -} - -/** - * JSONStringStreamController represents the transform controller that's able to transform the incoming - * new line delimited json content stream into entities and able to push the entity to the down stream - */ -interface JSONStringStreamController extends TransformStreamDefaultController { - buf?: string - pos?: number - enqueue: (s: T) => void -} - -/** - * getNewLineDelimitedJSONDecodingStream returns a TransformStream that's able to handle new line delimited json stream content into parsed entities - */ -function getNewLineDelimitedJSONDecodingStream(): TransformStream { - return new TransformStream({ - start(controller: JSONStringStreamController) { - controller.buf = '' - controller.pos = 0 - }, - - transform(chunk: string, controller: JSONStringStreamController) { - if (controller.buf === undefined) { - controller.buf = '' - } - if (controller.pos === undefined) { - controller.pos = 0 - } - controller.buf += chunk - while (controller.pos < controller.buf.length) { - if (controller.buf[controller.pos] === '\n') { - const line = controller.buf.substring(0, controller.pos) - const response = JSON.parse(line) - controller.enqueue(response.result) - controller.buf = controller.buf.substring(controller.pos + 1) - controller.pos = 0 - } else { - ++controller.pos - } - } - } - }) - -} - -/** - * getNotifyEntityArrivalSink takes the NotifyStreamEntityArrival callback and return - * a sink that will call the callback on entity arrival - * @param notifyCallback - */ -function getNotifyEntityArrivalSink(notifyCallback: NotifyStreamEntityArrival) { - return new WritableStream({ - write(entity: T) { - notifyCallback(entity) - } - }) -} - -type Primitive = string | boolean | number; -type RequestPayload = Record; -type FlattenedRequestPayload = Record>; - -/** - * Checks if given value is a plain object - * Logic copied and adapted from below source: - * https://github.com/char0n/ramda-adjunct/blob/master/src/isPlainObj.js - * @param {unknown} value - * @return {boolean} - */ -function isPlainObject(value: unknown): boolean { - const isObject = - Object.prototype.toString.call(value).slice(8, -1) === "Object"; - const isObjLike = value !== null && isObject; - - if (!isObjLike || !isObject) { - return false; - } - - const proto = Object.getPrototypeOf(value); - - const hasObjectConstructor = - typeof proto === "object" && - proto.constructor === Object.prototype.constructor; - - return hasObjectConstructor; -} - -/** - * Checks if given value is of a primitive type - * @param {unknown} value - * @return {boolean} - */ -function isPrimitive(value: unknown): boolean { - return ["string", "number", "boolean"].some(t => typeof value === t); -} - -/** - * Checks if given primitive is zero-value - * @param {Primitive} value - * @return {boolean} - */ -function isZeroValuePrimitive(value: Primitive): boolean { - return value === false || value === 0 || value === ""; -} - -/** - * Flattens a deeply nested request payload and returns an object - * with only primitive values and non-empty array of primitive values - * as per https://github.com/googleapis/googleapis/blob/master/google/api/http.proto - * @param {RequestPayload} requestPayload - * @param {String} path - * @return {FlattenedRequestPayload>} - */ -function flattenRequestPayload( - requestPayload: T, - path: string = "" -): FlattenedRequestPayload { - return Object.keys(requestPayload).reduce( - (acc: T, key: string): T => { - const value = requestPayload[key]; - const newPath = path ? [path, key].join(".") : key; - - const isNonEmptyPrimitiveArray = - Array.isArray(value) && - value.every(v => isPrimitive(v)) && - value.length > 0; - - const isNonZeroValuePrimitive = - isPrimitive(value) && !isZeroValuePrimitive(value as Primitive); - - let objectToMerge = {}; - - if (isPlainObject(value)) { - objectToMerge = flattenRequestPayload(value as RequestPayload, newPath); - } else if (isNonZeroValuePrimitive || isNonEmptyPrimitiveArray) { - objectToMerge = { [newPath]: value }; - } - - return { ...acc, ...objectToMerge }; - }, - {} as T - ) as FlattenedRequestPayload; -} - -/** - * Renders a deeply nested request payload into a string of URL search - * parameters by first flattening the request payload and then removing keys - * which are already present in the URL path. - * @param {RequestPayload} requestPayload - * @param {string[]} urlPathParams - * @return {string} - */ -export function renderURLSearchParams( - requestPayload: T, - urlPathParams: string[] = [] -): string { - const flattenedRequestPayload = flattenRequestPayload(requestPayload); - - const urlSearchParams = Object.keys(flattenedRequestPayload).reduce( - (acc: string[][], key: string): string[][] => { - // key should not be present in the url path as a parameter - const value = flattenedRequestPayload[key]; - if (urlPathParams.find(f => f === key)) { - return acc; - } - return Array.isArray(value) - ? [...acc, ...value.map(m => [key, m.toString()])] - : (acc = [...acc, [key, value.toString()]]); - }, - [] as string[][] - ); - - return new URLSearchParams(urlSearchParams).toString(); -} \ No newline at end of file diff --git a/webui/gen/ts/google/api/annotations.pb.ts b/webui/gen/ts/google/api/annotations.pb.ts deleted file mode 100644 index 56004c9f..00000000 --- a/webui/gen/ts/google/api/annotations.pb.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/webui/gen/ts/google/api/http.pb.ts b/webui/gen/ts/google/api/http.pb.ts deleted file mode 100644 index 9fe73dff..00000000 --- a/webui/gen/ts/google/api/http.pb.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck -/* -* This file is a generated Typescript file for GRPC Gateway, DO NOT MODIFY -*/ - -type Absent = { [k in Exclude]?: undefined }; -type OneOf = - | { [k in keyof T]?: undefined } - | ( - keyof T extends infer K ? - (K extends string & keyof T ? { [k in K]: T[K] } & Absent - : never) - : never); -export type Http = { - rules?: HttpRule[] - fullyDecodeReservedExpansion?: boolean -} - - -type BaseHttpRule = { - selector?: string - body?: string - responseBody?: string - additionalBindings?: HttpRule[] -} - -export type HttpRule = BaseHttpRule - & OneOf<{ get: string; put: string; post: string; delete: string; patch: string; custom: CustomHttpPattern }> - -export type CustomHttpPattern = { - kind?: string - path?: string -} \ No newline at end of file diff --git a/webui/gen/ts/google/api/http_pb.ts b/webui/gen/ts/google/api/http_pb.ts new file mode 100644 index 00000000..555c160e --- /dev/null +++ b/webui/gen/ts/google/api/http_pb.ts @@ -0,0 +1,547 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// @generated by protoc-gen-es v1.6.0 with parameter "target=ts" +// @generated from file google/api/http.proto (package google.api, syntax proto3) +/* eslint-disable */ +// @ts-nocheck + +import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; +import { Message, proto3 } from "@bufbuild/protobuf"; + +/** + * Defines the HTTP configuration for an API service. It contains a list of + * [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method + * to one or more HTTP REST API methods. + * + * @generated from message google.api.Http + */ +export class Http extends Message { + /** + * A list of HTTP configuration rules that apply to individual API methods. + * + * **NOTE:** All service configuration rules follow "last one wins" order. + * + * @generated from field: repeated google.api.HttpRule rules = 1; + */ + rules: HttpRule[] = []; + + /** + * When set to true, URL path parameters will be fully URI-decoded except in + * cases of single segment matches in reserved expansion, where "%2F" will be + * left encoded. + * + * The default behavior is to not decode RFC 6570 reserved characters in multi + * segment matches. + * + * @generated from field: bool fully_decode_reserved_expansion = 2; + */ + fullyDecodeReservedExpansion = false; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "google.api.Http"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "rules", kind: "message", T: HttpRule, repeated: true }, + { no: 2, name: "fully_decode_reserved_expansion", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Http { + return new Http().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Http { + return new Http().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Http { + return new Http().fromJsonString(jsonString, options); + } + + static equals(a: Http | PlainMessage | undefined, b: Http | PlainMessage | undefined): boolean { + return proto3.util.equals(Http, a, b); + } +} + +/** + * # gRPC Transcoding + * + * gRPC Transcoding is a feature for mapping between a gRPC method and one or + * more HTTP REST endpoints. It allows developers to build a single API service + * that supports both gRPC APIs and REST APIs. Many systems, including [Google + * APIs](https://github.com/googleapis/googleapis), + * [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC + * Gateway](https://github.com/grpc-ecosystem/grpc-gateway), + * and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature + * and use it for large scale production services. + * + * `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies + * how different portions of the gRPC request message are mapped to the URL + * path, URL query parameters, and HTTP request body. It also controls how the + * gRPC response message is mapped to the HTTP response body. `HttpRule` is + * typically specified as an `google.api.http` annotation on the gRPC method. + * + * Each mapping specifies a URL path template and an HTTP method. The path + * template may refer to one or more fields in the gRPC request message, as long + * as each field is a non-repeated field with a primitive (non-message) type. + * The path template controls how fields of the request message are mapped to + * the URL path. + * + * Example: + * + * service Messaging { + * rpc GetMessage(GetMessageRequest) returns (Message) { + * option (google.api.http) = { + * get: "/v1/{name=messages/*}" + * }; + * } + * } + * message GetMessageRequest { + * string name = 1; // Mapped to URL path. + * } + * message Message { + * string text = 1; // The resource content. + * } + * + * This enables an HTTP REST to gRPC mapping as below: + * + * HTTP | gRPC + * -----|----- + * `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")` + * + * Any fields in the request message which are not bound by the path template + * automatically become HTTP query parameters if there is no HTTP request body. + * For example: + * + * service Messaging { + * rpc GetMessage(GetMessageRequest) returns (Message) { + * option (google.api.http) = { + * get:"/v1/messages/{message_id}" + * }; + * } + * } + * message GetMessageRequest { + * message SubMessage { + * string subfield = 1; + * } + * string message_id = 1; // Mapped to URL path. + * int64 revision = 2; // Mapped to URL query parameter `revision`. + * SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`. + * } + * + * This enables a HTTP JSON to RPC mapping as below: + * + * HTTP | gRPC + * -----|----- + * `GET /v1/messages/123456?revision=2&sub.subfield=foo` | + * `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: + * "foo"))` + * + * Note that fields which are mapped to URL query parameters must have a + * primitive type or a repeated primitive type or a non-repeated message type. + * In the case of a repeated type, the parameter can be repeated in the URL + * as `...?param=A¶m=B`. In the case of a message type, each field of the + * message is mapped to a separate parameter, such as + * `...?foo.a=A&foo.b=B&foo.c=C`. + * + * For HTTP methods that allow a request body, the `body` field + * specifies the mapping. Consider a REST update method on the + * message resource collection: + * + * service Messaging { + * rpc UpdateMessage(UpdateMessageRequest) returns (Message) { + * option (google.api.http) = { + * patch: "/v1/messages/{message_id}" + * body: "message" + * }; + * } + * } + * message UpdateMessageRequest { + * string message_id = 1; // mapped to the URL + * Message message = 2; // mapped to the body + * } + * + * The following HTTP JSON to RPC mapping is enabled, where the + * representation of the JSON in the request body is determined by + * protos JSON encoding: + * + * HTTP | gRPC + * -----|----- + * `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: + * "123456" message { text: "Hi!" })` + * + * The special name `*` can be used in the body mapping to define that + * every field not bound by the path template should be mapped to the + * request body. This enables the following alternative definition of + * the update method: + * + * service Messaging { + * rpc UpdateMessage(Message) returns (Message) { + * option (google.api.http) = { + * patch: "/v1/messages/{message_id}" + * body: "*" + * }; + * } + * } + * message Message { + * string message_id = 1; + * string text = 2; + * } + * + * + * The following HTTP JSON to RPC mapping is enabled: + * + * HTTP | gRPC + * -----|----- + * `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: + * "123456" text: "Hi!")` + * + * Note that when using `*` in the body mapping, it is not possible to + * have HTTP parameters, as all fields not bound by the path end in + * the body. This makes this option more rarely used in practice when + * defining REST APIs. The common usage of `*` is in custom methods + * which don't use the URL at all for transferring data. + * + * It is possible to define multiple HTTP methods for one RPC by using + * the `additional_bindings` option. Example: + * + * service Messaging { + * rpc GetMessage(GetMessageRequest) returns (Message) { + * option (google.api.http) = { + * get: "/v1/messages/{message_id}" + * additional_bindings { + * get: "/v1/users/{user_id}/messages/{message_id}" + * } + * }; + * } + * } + * message GetMessageRequest { + * string message_id = 1; + * string user_id = 2; + * } + * + * This enables the following two alternative HTTP JSON to RPC mappings: + * + * HTTP | gRPC + * -----|----- + * `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` + * `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: + * "123456")` + * + * ## Rules for HTTP mapping + * + * 1. Leaf request fields (recursive expansion nested messages in the request + * message) are classified into three categories: + * - Fields referred by the path template. They are passed via the URL path. + * - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They + * are passed via the HTTP + * request body. + * - All other fields are passed via the URL query parameters, and the + * parameter name is the field path in the request message. A repeated + * field can be represented as multiple query parameters under the same + * name. + * 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL + * query parameter, all fields + * are passed via URL path and HTTP request body. + * 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP + * request body, all + * fields are passed via URL path and URL query parameters. + * + * ### Path template syntax + * + * Template = "/" Segments [ Verb ] ; + * Segments = Segment { "/" Segment } ; + * Segment = "*" | "**" | LITERAL | Variable ; + * Variable = "{" FieldPath [ "=" Segments ] "}" ; + * FieldPath = IDENT { "." IDENT } ; + * Verb = ":" LITERAL ; + * + * The syntax `*` matches a single URL path segment. The syntax `**` matches + * zero or more URL path segments, which must be the last part of the URL path + * except the `Verb`. + * + * The syntax `Variable` matches part of the URL path as specified by its + * template. A variable template must not contain other variables. If a variable + * matches a single path segment, its template may be omitted, e.g. `{var}` + * is equivalent to `{var=*}`. + * + * The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL` + * contains any reserved character, such characters should be percent-encoded + * before the matching. + * + * If a variable contains exactly one path segment, such as `"{var}"` or + * `"{var=*}"`, when such a variable is expanded into a URL path on the client + * side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The + * server side does the reverse decoding. Such variables show up in the + * [Discovery + * Document](https://developers.google.com/discovery/v1/reference/apis) as + * `{var}`. + * + * If a variable contains multiple path segments, such as `"{var=foo/*}"` + * or `"{var=**}"`, when such a variable is expanded into a URL path on the + * client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. + * The server side does the reverse decoding, except "%2F" and "%2f" are left + * unchanged. Such variables show up in the + * [Discovery + * Document](https://developers.google.com/discovery/v1/reference/apis) as + * `{+var}`. + * + * ## Using gRPC API Service Configuration + * + * gRPC API Service Configuration (service config) is a configuration language + * for configuring a gRPC service to become a user-facing product. The + * service config is simply the YAML representation of the `google.api.Service` + * proto message. + * + * As an alternative to annotating your proto file, you can configure gRPC + * transcoding in your service config YAML files. You do this by specifying a + * `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same + * effect as the proto annotation. This can be particularly useful if you + * have a proto that is reused in multiple services. Note that any transcoding + * specified in the service config will override any matching transcoding + * configuration in the proto. + * + * Example: + * + * http: + * rules: + * # Selects a gRPC method and applies HttpRule to it. + * - selector: example.v1.Messaging.GetMessage + * get: /v1/messages/{message_id}/{sub.subfield} + * + * ## Special notes + * + * When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the + * proto to JSON conversion must follow the [proto3 + * specification](https://developers.google.com/protocol-buffers/docs/proto3#json). + * + * While the single segment variable follows the semantics of + * [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String + * Expansion, the multi segment variable **does not** follow RFC 6570 Section + * 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion + * does not expand special characters like `?` and `#`, which would lead + * to invalid URLs. As the result, gRPC Transcoding uses a custom encoding + * for multi segment variables. + * + * The path variables **must not** refer to any repeated or mapped field, + * because client libraries are not capable of handling such variable expansion. + * + * The path variables **must not** capture the leading "/" character. The reason + * is that the most common use case "{var}" does not capture the leading "/" + * character. For consistency, all path variables must share the same behavior. + * + * Repeated message fields must not be mapped to URL query parameters, because + * no client library can support such complicated mapping. + * + * If an API needs to use a JSON array for request or response body, it can map + * the request or response body to a repeated field. However, some gRPC + * Transcoding implementations may not support this feature. + * + * @generated from message google.api.HttpRule + */ +export class HttpRule extends Message { + /** + * Selects a method to which this rule applies. + * + * Refer to [selector][google.api.DocumentationRule.selector] for syntax + * details. + * + * @generated from field: string selector = 1; + */ + selector = ""; + + /** + * Determines the URL pattern is matched by this rules. This pattern can be + * used with any of the {get|put|post|delete|patch} methods. A custom method + * can be defined using the 'custom' field. + * + * @generated from oneof google.api.HttpRule.pattern + */ + pattern: { + /** + * Maps to HTTP GET. Used for listing and getting information about + * resources. + * + * @generated from field: string get = 2; + */ + value: string; + case: "get"; + } | { + /** + * Maps to HTTP PUT. Used for replacing a resource. + * + * @generated from field: string put = 3; + */ + value: string; + case: "put"; + } | { + /** + * Maps to HTTP POST. Used for creating a resource or performing an action. + * + * @generated from field: string post = 4; + */ + value: string; + case: "post"; + } | { + /** + * Maps to HTTP DELETE. Used for deleting a resource. + * + * @generated from field: string delete = 5; + */ + value: string; + case: "delete"; + } | { + /** + * Maps to HTTP PATCH. Used for updating a resource. + * + * @generated from field: string patch = 6; + */ + value: string; + case: "patch"; + } | { + /** + * The custom pattern is used for specifying an HTTP method that is not + * included in the `pattern` field, such as HEAD, or "*" to leave the + * HTTP method unspecified for this rule. The wild-card rule is useful + * for services that provide content to Web (HTML) clients. + * + * @generated from field: google.api.CustomHttpPattern custom = 8; + */ + value: CustomHttpPattern; + case: "custom"; + } | { case: undefined; value?: undefined } = { case: undefined }; + + /** + * The name of the request field whose value is mapped to the HTTP request + * body, or `*` for mapping all request fields not captured by the path + * pattern to the HTTP body, or omitted for not having any HTTP request body. + * + * NOTE: the referred field must be present at the top-level of the request + * message type. + * + * @generated from field: string body = 7; + */ + body = ""; + + /** + * Optional. The name of the response field whose value is mapped to the HTTP + * response body. When omitted, the entire response message will be used + * as the HTTP response body. + * + * NOTE: The referred field must be present at the top-level of the response + * message type. + * + * @generated from field: string response_body = 12; + */ + responseBody = ""; + + /** + * Additional HTTP bindings for the selector. Nested bindings must + * not contain an `additional_bindings` field themselves (that is, + * the nesting may only be one level deep). + * + * @generated from field: repeated google.api.HttpRule additional_bindings = 11; + */ + additionalBindings: HttpRule[] = []; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "google.api.HttpRule"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "selector", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "get", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "pattern" }, + { no: 3, name: "put", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "pattern" }, + { no: 4, name: "post", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "pattern" }, + { no: 5, name: "delete", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "pattern" }, + { no: 6, name: "patch", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "pattern" }, + { no: 8, name: "custom", kind: "message", T: CustomHttpPattern, oneof: "pattern" }, + { no: 7, name: "body", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 12, name: "response_body", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 11, name: "additional_bindings", kind: "message", T: HttpRule, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): HttpRule { + return new HttpRule().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): HttpRule { + return new HttpRule().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): HttpRule { + return new HttpRule().fromJsonString(jsonString, options); + } + + static equals(a: HttpRule | PlainMessage | undefined, b: HttpRule | PlainMessage | undefined): boolean { + return proto3.util.equals(HttpRule, a, b); + } +} + +/** + * A custom pattern is used for defining custom HTTP verb. + * + * @generated from message google.api.CustomHttpPattern + */ +export class CustomHttpPattern extends Message { + /** + * The name of this custom HTTP verb. + * + * @generated from field: string kind = 1; + */ + kind = ""; + + /** + * The path matched by this custom verb. + * + * @generated from field: string path = 2; + */ + path = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "google.api.CustomHttpPattern"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "kind", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "path", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): CustomHttpPattern { + return new CustomHttpPattern().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): CustomHttpPattern { + return new CustomHttpPattern().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): CustomHttpPattern { + return new CustomHttpPattern().fromJsonString(jsonString, options); + } + + static equals(a: CustomHttpPattern | PlainMessage | undefined, b: CustomHttpPattern | PlainMessage | undefined): boolean { + return proto3.util.equals(CustomHttpPattern, a, b); + } +} + diff --git a/webui/gen/ts/types/value.pb.ts b/webui/gen/ts/types/value.pb.ts deleted file mode 100644 index a35d1c4f..00000000 --- a/webui/gen/ts/types/value.pb.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck -/* -* This file is a generated Typescript file for GRPC Gateway, DO NOT MODIFY -*/ -export type StringValue = { - value?: string -} - -export type StringList = { - values?: string[] -} - -export type Int64Value = { - value?: string -} \ No newline at end of file diff --git a/webui/gen/ts/types/value_pb.ts b/webui/gen/ts/types/value_pb.ts new file mode 100644 index 00000000..7dd9b4d3 --- /dev/null +++ b/webui/gen/ts/types/value_pb.ts @@ -0,0 +1,119 @@ +// @generated by protoc-gen-es v1.6.0 with parameter "target=ts" +// @generated from file types/value.proto (package types, syntax proto3) +/* eslint-disable */ +// @ts-nocheck + +import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; +import { Message, proto3, protoInt64 } from "@bufbuild/protobuf"; + +/** + * @generated from message types.StringValue + */ +export class StringValue extends Message { + /** + * @generated from field: string value = 1; + */ + value = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "types.StringValue"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "value", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): StringValue { + return new StringValue().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): StringValue { + return new StringValue().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): StringValue { + return new StringValue().fromJsonString(jsonString, options); + } + + static equals(a: StringValue | PlainMessage | undefined, b: StringValue | PlainMessage | undefined): boolean { + return proto3.util.equals(StringValue, a, b); + } +} + +/** + * @generated from message types.StringList + */ +export class StringList extends Message { + /** + * @generated from field: repeated string values = 1; + */ + values: string[] = []; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "types.StringList"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "values", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): StringList { + return new StringList().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): StringList { + return new StringList().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): StringList { + return new StringList().fromJsonString(jsonString, options); + } + + static equals(a: StringList | PlainMessage | undefined, b: StringList | PlainMessage | undefined): boolean { + return proto3.util.equals(StringList, a, b); + } +} + +/** + * @generated from message types.Int64Value + */ +export class Int64Value extends Message { + /** + * @generated from field: int64 value = 1; + */ + value = protoInt64.zero; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "types.Int64Value"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "value", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Int64Value { + return new Int64Value().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Int64Value { + return new Int64Value().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Int64Value { + return new Int64Value().fromJsonString(jsonString, options); + } + + static equals(a: Int64Value | PlainMessage | undefined, b: Int64Value | PlainMessage | undefined): boolean { + return proto3.util.equals(Int64Value, a, b); + } +} + diff --git a/webui/gen/ts/v1/config.pb.ts b/webui/gen/ts/v1/config.pb.ts deleted file mode 100644 index 78d01f94..00000000 --- a/webui/gen/ts/v1/config.pb.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck -/* -* This file is a generated Typescript file for GRPC Gateway, DO NOT MODIFY -*/ -export type Config = { - modno?: number - host?: string - repos?: Repo[] - plans?: Plan[] -} - -export type Repo = { - id?: string - uri?: string - password?: string - env?: string[] - flags?: string[] - prunePolicy?: PrunePolicy -} - -export type Plan = { - id?: string - repo?: string - paths?: string[] - excludes?: string[] - cron?: string - retention?: RetentionPolicy -} - -export type RetentionPolicy = { - maxUnusedLimit?: string - keepLastN?: number - keepHourly?: number - keepDaily?: number - keepWeekly?: number - keepMonthly?: number - keepYearly?: number - keepWithinDuration?: string -} - -export type PrunePolicy = { - maxFrequencyDays?: number - maxUnusedPercent?: number - maxUnusedBytes?: number -} \ No newline at end of file diff --git a/webui/gen/ts/v1/config_pb.ts b/webui/gen/ts/v1/config_pb.ts new file mode 100644 index 00000000..c3f1e6dc --- /dev/null +++ b/webui/gen/ts/v1/config_pb.ts @@ -0,0 +1,434 @@ +// @generated by protoc-gen-es v1.6.0 with parameter "target=ts" +// @generated from file v1/config.proto (package v1, syntax proto3) +/* eslint-disable */ +// @ts-nocheck + +import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; +import { Message, proto3 } from "@bufbuild/protobuf"; + +/** + * Config is the top level config object for restic UI. + * + * @generated from message v1.Config + */ +export class Config extends Message { + /** + * modification number, used for read-modify-write consistency in the UI. Incremented on every write. + * + * @generated from field: int32 modno = 1; + */ + modno = 0; + + /** + * override the hostname tagged on backups. If provided it will be used in addition to tags to group backups. + * + * @generated from field: string host = 2; + */ + host = ""; + + /** + * @generated from field: repeated v1.Repo repos = 3; + */ + repos: Repo[] = []; + + /** + * @generated from field: repeated v1.Plan plans = 4; + */ + plans: Plan[] = []; + + /** + * @generated from field: repeated v1.User users = 5; + */ + users: User[] = []; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.Config"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "modno", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + { no: 2, name: "host", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 3, name: "repos", kind: "message", T: Repo, repeated: true }, + { no: 4, name: "plans", kind: "message", T: Plan, repeated: true }, + { no: 5, name: "users", kind: "message", T: User, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Config { + return new Config().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Config { + return new Config().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Config { + return new Config().fromJsonString(jsonString, options); + } + + static equals(a: Config | PlainMessage | undefined, b: Config | PlainMessage | undefined): boolean { + return proto3.util.equals(Config, a, b); + } +} + +/** + * @generated from message v1.Repo + */ +export class Repo extends Message { + /** + * unique but human readable ID for this repo. + * + * @generated from field: string id = 1; + */ + id = ""; + + /** + * restic repo URI + * + * @generated from field: string uri = 2; + */ + uri = ""; + + /** + * plaintext password + * + * @generated from field: string password = 3; + */ + password = ""; + + /** + * extra environment variables to set for restic. + * + * @generated from field: repeated string env = 4; + */ + env: string[] = []; + + /** + * extra flags set on the restic command. + * + * @generated from field: repeated string flags = 5; + */ + flags: string[] = []; + + /** + * policy for when to run prune. + * + * @generated from field: v1.PrunePolicy prune_policy = 6; + */ + prunePolicy?: PrunePolicy; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.Repo"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "uri", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 3, name: "password", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 4, name: "env", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + { no: 5, name: "flags", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + { no: 6, name: "prune_policy", kind: "message", T: PrunePolicy }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Repo { + return new Repo().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Repo { + return new Repo().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Repo { + return new Repo().fromJsonString(jsonString, options); + } + + static equals(a: Repo | PlainMessage | undefined, b: Repo | PlainMessage | undefined): boolean { + return proto3.util.equals(Repo, a, b); + } +} + +/** + * @generated from message v1.Plan + */ +export class Plan extends Message { + /** + * unique but human readable ID for this plan. + * + * @generated from field: string id = 1; + */ + id = ""; + + /** + * ID of the repo to use. + * + * @generated from field: string repo = 2; + */ + repo = ""; + + /** + * paths to include in the backup. + * + * @generated from field: repeated string paths = 4; + */ + paths: string[] = []; + + /** + * glob patterns to exclude. + * + * @generated from field: repeated string excludes = 5; + */ + excludes: string[] = []; + + /** + * cron expression describing the backup schedule. + * + * @generated from field: string cron = 6; + */ + cron = ""; + + /** + * retention policy for snapshots. + * + * @generated from field: v1.RetentionPolicy retention = 7; + */ + retention?: RetentionPolicy; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.Plan"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "repo", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 4, name: "paths", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + { no: 5, name: "excludes", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + { no: 6, name: "cron", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 7, name: "retention", kind: "message", T: RetentionPolicy }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Plan { + return new Plan().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Plan { + return new Plan().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Plan { + return new Plan().fromJsonString(jsonString, options); + } + + static equals(a: Plan | PlainMessage | undefined, b: Plan | PlainMessage | undefined): boolean { + return proto3.util.equals(Plan, a, b); + } +} + +/** + * @generated from message v1.RetentionPolicy + */ +export class RetentionPolicy extends Message { + /** + * max_unused_limit is used to decide when forget should be run. + * + * e.g. a percentage i.e. 25% or a number of megabytes. + * + * @generated from field: string max_unused_limit = 1; + */ + maxUnusedLimit = ""; + + /** + * keep the last n snapshots. + * + * @generated from field: int32 keep_last_n = 2; + */ + keepLastN = 0; + + /** + * keep the last n hourly snapshots. + * + * @generated from field: int32 keep_hourly = 3; + */ + keepHourly = 0; + + /** + * keep the last n daily snapshots. + * + * @generated from field: int32 keep_daily = 4; + */ + keepDaily = 0; + + /** + * keep the last n weekly snapshots. + * + * @generated from field: int32 keep_weekly = 5; + */ + keepWeekly = 0; + + /** + * keep the last n monthly snapshots. + * + * @generated from field: int32 keep_monthly = 6; + */ + keepMonthly = 0; + + /** + * keep the last n yearly snapshots. + * + * @generated from field: int32 keep_yearly = 7; + */ + keepYearly = 0; + + /** + * keep snapshots within a duration e.g. 1y2m3d4h5m6s + * + * @generated from field: string keep_within_duration = 8; + */ + keepWithinDuration = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.RetentionPolicy"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "max_unused_limit", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "keep_last_n", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + { no: 3, name: "keep_hourly", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + { no: 4, name: "keep_daily", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + { no: 5, name: "keep_weekly", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + { no: 6, name: "keep_monthly", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + { no: 7, name: "keep_yearly", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + { no: 8, name: "keep_within_duration", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): RetentionPolicy { + return new RetentionPolicy().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): RetentionPolicy { + return new RetentionPolicy().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): RetentionPolicy { + return new RetentionPolicy().fromJsonString(jsonString, options); + } + + static equals(a: RetentionPolicy | PlainMessage | undefined, b: RetentionPolicy | PlainMessage | undefined): boolean { + return proto3.util.equals(RetentionPolicy, a, b); + } +} + +/** + * @generated from message v1.PrunePolicy + */ +export class PrunePolicy extends Message { + /** + * max frequency of prune runs in days. If 0, prune will be run on every backup. + * + * @generated from field: int32 max_frequency_days = 1; + */ + maxFrequencyDays = 0; + + /** + * max percentage of repo size that can be unused before prune is run. + * + * @generated from field: int32 max_unused_percent = 100; + */ + maxUnusedPercent = 0; + + /** + * max number of bytes that can be unused before prune is run. + * + * @generated from field: int32 max_unused_bytes = 101; + */ + maxUnusedBytes = 0; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.PrunePolicy"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "max_frequency_days", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + { no: 100, name: "max_unused_percent", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + { no: 101, name: "max_unused_bytes", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): PrunePolicy { + return new PrunePolicy().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): PrunePolicy { + return new PrunePolicy().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): PrunePolicy { + return new PrunePolicy().fromJsonString(jsonString, options); + } + + static equals(a: PrunePolicy | PlainMessage | undefined, b: PrunePolicy | PlainMessage | undefined): boolean { + return proto3.util.equals(PrunePolicy, a, b); + } +} + +/** + * @generated from message v1.User + */ +export class User extends Message { + /** + * @generated from field: string name = 1; + */ + name = ""; + + /** + * @generated from oneof v1.User.password + */ + password: { + /** + * @generated from field: string password_bcrypt = 2; + */ + value: string; + case: "passwordBcrypt"; + } | { case: undefined; value?: undefined } = { case: undefined }; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.User"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "password_bcrypt", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "password" }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): User { + return new User().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): User { + return new User().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): User { + return new User().fromJsonString(jsonString, options); + } + + static equals(a: User | PlainMessage | undefined, b: User | PlainMessage | undefined): boolean { + return proto3.util.equals(User, a, b); + } +} + diff --git a/webui/gen/ts/v1/events.pb.ts b/webui/gen/ts/v1/events.pb.ts deleted file mode 100644 index 62dfd6c6..00000000 --- a/webui/gen/ts/v1/events.pb.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck -/* -* This file is a generated Typescript file for GRPC Gateway, DO NOT MODIFY -*/ - -type Absent = { [k in Exclude]?: undefined }; -type OneOf = - | { [k in keyof T]?: undefined } - | ( - keyof T extends infer K ? - (K extends string & keyof T ? { [k in K]: T[K] } & Absent - : never) - : never); - -export enum Status { - UNKNOWN = "UNKNOWN", - IN_PROGRESS = "IN_PROGRESS", - SUCCESS = "SUCCESS", - FAILED = "FAILED", -} - - -type BaseEvent = { - timestamp?: string -} - -export type Event = BaseEvent - & OneOf<{ log: LogEvent; backupStatusChange: BackupStatusEvent }> - -export type LogEvent = { - message?: string -} - -export type BackupStatusEvent = { - plan?: string - status?: Status - percent?: number -} \ No newline at end of file diff --git a/webui/gen/ts/v1/operations.pb.ts b/webui/gen/ts/v1/operations.pb.ts deleted file mode 100644 index aa83d8eb..00000000 --- a/webui/gen/ts/v1/operations.pb.ts +++ /dev/null @@ -1,84 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck -/* -* This file is a generated Typescript file for GRPC Gateway, DO NOT MODIFY -*/ - -import * as V1Config from "./config.pb" -import * as V1Restic from "./restic.pb" - -type Absent = { [k in Exclude]?: undefined }; -type OneOf = - | { [k in keyof T]?: undefined } - | ( - keyof T extends infer K ? - (K extends string & keyof T ? { [k in K]: T[K] } & Absent - : never) - : never); - -export enum OperationEventType { - EVENT_UNKNOWN = "EVENT_UNKNOWN", - EVENT_CREATED = "EVENT_CREATED", - EVENT_UPDATED = "EVENT_UPDATED", - EVENT_DELETED = "EVENT_DELETED", -} - -export enum OperationStatus { - STATUS_UNKNOWN = "STATUS_UNKNOWN", - STATUS_PENDING = "STATUS_PENDING", - STATUS_INPROGRESS = "STATUS_INPROGRESS", - STATUS_SUCCESS = "STATUS_SUCCESS", - STATUS_WARNING = "STATUS_WARNING", - STATUS_ERROR = "STATUS_ERROR", - STATUS_SYSTEM_CANCELLED = "STATUS_SYSTEM_CANCELLED", - STATUS_USER_CANCELLED = "STATUS_USER_CANCELLED", -} - -export type OperationList = { - operations?: Operation[] -} - - -type BaseOperation = { - id?: string - repoId?: string - planId?: string - snapshotId?: string - status?: OperationStatus - unixTimeStartMs?: string - unixTimeEndMs?: string - displayMessage?: string -} - -export type Operation = BaseOperation - & OneOf<{ operationBackup: OperationBackup; operationIndexSnapshot: OperationIndexSnapshot; operationForget: OperationForget; operationPrune: OperationPrune; operationRestore: OperationRestore }> - -export type OperationEvent = { - type?: OperationEventType - operation?: Operation -} - -export type OperationBackup = { - lastStatus?: V1Restic.BackupProgressEntry -} - -export type OperationIndexSnapshot = { - snapshot?: V1Restic.ResticSnapshot - forgot?: boolean - forgotByOp?: string -} - -export type OperationForget = { - forget?: V1Restic.ResticSnapshot[] - policy?: V1Config.RetentionPolicy -} - -export type OperationPrune = { - output?: string -} - -export type OperationRestore = { - path?: string - target?: string - status?: V1Restic.RestoreProgressEntry -} \ No newline at end of file diff --git a/webui/gen/ts/v1/operations_pb.ts b/webui/gen/ts/v1/operations_pb.ts new file mode 100644 index 00000000..5feadc9d --- /dev/null +++ b/webui/gen/ts/v1/operations_pb.ts @@ -0,0 +1,564 @@ +// @generated by protoc-gen-es v1.6.0 with parameter "target=ts" +// @generated from file v1/operations.proto (package v1, syntax proto3) +/* eslint-disable */ +// @ts-nocheck + +import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; +import { Message, proto3, protoInt64 } from "@bufbuild/protobuf"; +import { BackupProgressEntry, ResticSnapshot, RestoreProgressEntry } from "./restic_pb.js"; +import { RetentionPolicy } from "./config_pb.js"; + +/** + * OperationEventType indicates whether the operation was created or updated + * + * @generated from enum v1.OperationEventType + */ +export enum OperationEventType { + /** + * @generated from enum value: EVENT_UNKNOWN = 0; + */ + EVENT_UNKNOWN = 0, + + /** + * @generated from enum value: EVENT_CREATED = 1; + */ + EVENT_CREATED = 1, + + /** + * @generated from enum value: EVENT_UPDATED = 2; + */ + EVENT_UPDATED = 2, + + /** + * @generated from enum value: EVENT_DELETED = 3; + */ + EVENT_DELETED = 3, +} +// Retrieve enum metadata with: proto3.getEnumType(OperationEventType) +proto3.util.setEnumType(OperationEventType, "v1.OperationEventType", [ + { no: 0, name: "EVENT_UNKNOWN" }, + { no: 1, name: "EVENT_CREATED" }, + { no: 2, name: "EVENT_UPDATED" }, + { no: 3, name: "EVENT_DELETED" }, +]); + +/** + * @generated from enum v1.OperationStatus + */ +export enum OperationStatus { + /** + * used to indicate that the status is unknown. + * + * @generated from enum value: STATUS_UNKNOWN = 0; + */ + STATUS_UNKNOWN = 0, + + /** + * used to indicate that the operation is pending. + * + * @generated from enum value: STATUS_PENDING = 1; + */ + STATUS_PENDING = 1, + + /** + * used to indicate that the operation is in progress. + * + * @generated from enum value: STATUS_INPROGRESS = 2; + */ + STATUS_INPROGRESS = 2, + + /** + * used to indicate that the operation completed successfully. + * + * @generated from enum value: STATUS_SUCCESS = 3; + */ + STATUS_SUCCESS = 3, + + /** + * used to indicate that the operation completed with warnings. + * + * @generated from enum value: STATUS_WARNING = 7; + */ + STATUS_WARNING = 7, + + /** + * used to indicate that the operation failed. + * + * @generated from enum value: STATUS_ERROR = 4; + */ + STATUS_ERROR = 4, + + /** + * indicates operation cancelled by the system. + * + * @generated from enum value: STATUS_SYSTEM_CANCELLED = 5; + */ + STATUS_SYSTEM_CANCELLED = 5, + + /** + * indicates operation cancelled by the user. + * + * @generated from enum value: STATUS_USER_CANCELLED = 6; + */ + STATUS_USER_CANCELLED = 6, +} +// Retrieve enum metadata with: proto3.getEnumType(OperationStatus) +proto3.util.setEnumType(OperationStatus, "v1.OperationStatus", [ + { no: 0, name: "STATUS_UNKNOWN" }, + { no: 1, name: "STATUS_PENDING" }, + { no: 2, name: "STATUS_INPROGRESS" }, + { no: 3, name: "STATUS_SUCCESS" }, + { no: 7, name: "STATUS_WARNING" }, + { no: 4, name: "STATUS_ERROR" }, + { no: 5, name: "STATUS_SYSTEM_CANCELLED" }, + { no: 6, name: "STATUS_USER_CANCELLED" }, +]); + +/** + * @generated from message v1.OperationList + */ +export class OperationList extends Message { + /** + * @generated from field: repeated v1.Operation operations = 1; + */ + operations: Operation[] = []; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.OperationList"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "operations", kind: "message", T: Operation, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): OperationList { + return new OperationList().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): OperationList { + return new OperationList().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): OperationList { + return new OperationList().fromJsonString(jsonString, options); + } + + static equals(a: OperationList | PlainMessage | undefined, b: OperationList | PlainMessage | undefined): boolean { + return proto3.util.equals(OperationList, a, b); + } +} + +/** + * @generated from message v1.Operation + */ +export class Operation extends Message { + /** + * required, primary ID of the operation. ID is sequential based on creation time of the operation. + * + * @generated from field: int64 id = 1; + */ + id = protoInt64.zero; + + /** + * required, repo id if associated with a repo + * + * @generated from field: string repo_id = 2; + */ + repoId = ""; + + /** + * required, plan id if associated with a plan + * + * @generated from field: string plan_id = 3; + */ + planId = ""; + + /** + * optional snapshot id if associated with a snapshot. + * + * @generated from field: string snapshot_id = 8; + */ + snapshotId = ""; + + /** + * @generated from field: v1.OperationStatus status = 4; + */ + status = OperationStatus.STATUS_UNKNOWN; + + /** + * required, unix time in milliseconds of the operation's creation (ID is derived from this) + * + * @generated from field: int64 unix_time_start_ms = 5; + */ + unixTimeStartMs = protoInt64.zero; + + /** + * optional, unix time in milliseconds of the operation's completion + * + * @generated from field: int64 unix_time_end_ms = 6; + */ + unixTimeEndMs = protoInt64.zero; + + /** + * optional, human readable context message, typically an error message. + * + * @generated from field: string display_message = 7; + */ + displayMessage = ""; + + /** + * @generated from oneof v1.Operation.op + */ + op: { + /** + * @generated from field: v1.OperationBackup operation_backup = 100; + */ + value: OperationBackup; + case: "operationBackup"; + } | { + /** + * @generated from field: v1.OperationIndexSnapshot operation_index_snapshot = 101; + */ + value: OperationIndexSnapshot; + case: "operationIndexSnapshot"; + } | { + /** + * @generated from field: v1.OperationForget operation_forget = 102; + */ + value: OperationForget; + case: "operationForget"; + } | { + /** + * @generated from field: v1.OperationPrune operation_prune = 103; + */ + value: OperationPrune; + case: "operationPrune"; + } | { + /** + * @generated from field: v1.OperationRestore operation_restore = 104; + */ + value: OperationRestore; + case: "operationRestore"; + } | { case: undefined; value?: undefined } = { case: undefined }; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.Operation"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "id", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 2, name: "repo_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 3, name: "plan_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 8, name: "snapshot_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 4, name: "status", kind: "enum", T: proto3.getEnumType(OperationStatus) }, + { no: 5, name: "unix_time_start_ms", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 6, name: "unix_time_end_ms", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 7, name: "display_message", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 100, name: "operation_backup", kind: "message", T: OperationBackup, oneof: "op" }, + { no: 101, name: "operation_index_snapshot", kind: "message", T: OperationIndexSnapshot, oneof: "op" }, + { no: 102, name: "operation_forget", kind: "message", T: OperationForget, oneof: "op" }, + { no: 103, name: "operation_prune", kind: "message", T: OperationPrune, oneof: "op" }, + { no: 104, name: "operation_restore", kind: "message", T: OperationRestore, oneof: "op" }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Operation { + return new Operation().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Operation { + return new Operation().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Operation { + return new Operation().fromJsonString(jsonString, options); + } + + static equals(a: Operation | PlainMessage | undefined, b: Operation | PlainMessage | undefined): boolean { + return proto3.util.equals(Operation, a, b); + } +} + +/** + * OperationEvent is used in the wireformat to stream operation changes to clients + * + * @generated from message v1.OperationEvent + */ +export class OperationEvent extends Message { + /** + * @generated from field: v1.OperationEventType type = 1; + */ + type = OperationEventType.EVENT_UNKNOWN; + + /** + * @generated from field: v1.Operation operation = 2; + */ + operation?: Operation; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.OperationEvent"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "type", kind: "enum", T: proto3.getEnumType(OperationEventType) }, + { no: 2, name: "operation", kind: "message", T: Operation }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): OperationEvent { + return new OperationEvent().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): OperationEvent { + return new OperationEvent().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): OperationEvent { + return new OperationEvent().fromJsonString(jsonString, options); + } + + static equals(a: OperationEvent | PlainMessage | undefined, b: OperationEvent | PlainMessage | undefined): boolean { + return proto3.util.equals(OperationEvent, a, b); + } +} + +/** + * @generated from message v1.OperationBackup + */ +export class OperationBackup extends Message { + /** + * @generated from field: v1.BackupProgressEntry last_status = 3; + */ + lastStatus?: BackupProgressEntry; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.OperationBackup"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 3, name: "last_status", kind: "message", T: BackupProgressEntry }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): OperationBackup { + return new OperationBackup().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): OperationBackup { + return new OperationBackup().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): OperationBackup { + return new OperationBackup().fromJsonString(jsonString, options); + } + + static equals(a: OperationBackup | PlainMessage | undefined, b: OperationBackup | PlainMessage | undefined): boolean { + return proto3.util.equals(OperationBackup, a, b); + } +} + +/** + * OperationIndexSnapshot tracks that a snapshot was detected by backrest. + * + * @generated from message v1.OperationIndexSnapshot + */ +export class OperationIndexSnapshot extends Message { + /** + * the snapshot that was indexed. + * + * @generated from field: v1.ResticSnapshot snapshot = 2; + */ + snapshot?: ResticSnapshot; + + /** + * tracks whether this snapshot is forgotten yet. + * + * @generated from field: bool forgot = 3; + */ + forgot = false; + + /** + * ID of a forget operation that removed this snapshot. + * + * @generated from field: int64 forgot_by_op = 4; + */ + forgotByOp = protoInt64.zero; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.OperationIndexSnapshot"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 2, name: "snapshot", kind: "message", T: ResticSnapshot }, + { no: 3, name: "forgot", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + { no: 4, name: "forgot_by_op", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): OperationIndexSnapshot { + return new OperationIndexSnapshot().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): OperationIndexSnapshot { + return new OperationIndexSnapshot().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): OperationIndexSnapshot { + return new OperationIndexSnapshot().fromJsonString(jsonString, options); + } + + static equals(a: OperationIndexSnapshot | PlainMessage | undefined, b: OperationIndexSnapshot | PlainMessage | undefined): boolean { + return proto3.util.equals(OperationIndexSnapshot, a, b); + } +} + +/** + * OperationForget tracks a forget operation. + * + * @generated from message v1.OperationForget + */ +export class OperationForget extends Message { + /** + * @generated from field: repeated v1.ResticSnapshot forget = 1; + */ + forget: ResticSnapshot[] = []; + + /** + * @generated from field: v1.RetentionPolicy policy = 2; + */ + policy?: RetentionPolicy; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.OperationForget"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "forget", kind: "message", T: ResticSnapshot, repeated: true }, + { no: 2, name: "policy", kind: "message", T: RetentionPolicy }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): OperationForget { + return new OperationForget().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): OperationForget { + return new OperationForget().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): OperationForget { + return new OperationForget().fromJsonString(jsonString, options); + } + + static equals(a: OperationForget | PlainMessage | undefined, b: OperationForget | PlainMessage | undefined): boolean { + return proto3.util.equals(OperationForget, a, b); + } +} + +/** + * OperationPrune tracks a prune operation. + * + * @generated from message v1.OperationPrune + */ +export class OperationPrune extends Message { + /** + * @generated from field: string output = 1; + */ + output = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.OperationPrune"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "output", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): OperationPrune { + return new OperationPrune().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): OperationPrune { + return new OperationPrune().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): OperationPrune { + return new OperationPrune().fromJsonString(jsonString, options); + } + + static equals(a: OperationPrune | PlainMessage | undefined, b: OperationPrune | PlainMessage | undefined): boolean { + return proto3.util.equals(OperationPrune, a, b); + } +} + +/** + * @generated from message v1.OperationRestore + */ +export class OperationRestore extends Message { + /** + * path in the snapshot to restore. + * + * @generated from field: string path = 1; + */ + path = ""; + + /** + * location to restore it to. + * + * @generated from field: string target = 2; + */ + target = ""; + + /** + * status of the restore. + * + * @generated from field: v1.RestoreProgressEntry status = 3; + */ + status?: RestoreProgressEntry; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.OperationRestore"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "path", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "target", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 3, name: "status", kind: "message", T: RestoreProgressEntry }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): OperationRestore { + return new OperationRestore().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): OperationRestore { + return new OperationRestore().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): OperationRestore { + return new OperationRestore().fromJsonString(jsonString, options); + } + + static equals(a: OperationRestore | PlainMessage | undefined, b: OperationRestore | PlainMessage | undefined): boolean { + return proto3.util.equals(OperationRestore, a, b); + } +} + diff --git a/webui/gen/ts/v1/restic.pb.ts b/webui/gen/ts/v1/restic.pb.ts deleted file mode 100644 index 40b07e6d..00000000 --- a/webui/gen/ts/v1/restic.pb.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck -/* -* This file is a generated Typescript file for GRPC Gateway, DO NOT MODIFY -*/ - -type Absent = { [k in Exclude]?: undefined }; -type OneOf = - | { [k in keyof T]?: undefined } - | ( - keyof T extends infer K ? - (K extends string & keyof T ? { [k in K]: T[K] } & Absent - : never) - : never); -export type ResticSnapshot = { - id?: string - unixTimeMs?: string - hostname?: string - username?: string - tree?: string - parent?: string - paths?: string[] - tags?: string[] -} - -export type ResticSnapshotList = { - snapshots?: ResticSnapshot[] -} - - -type BaseBackupProgressEntry = { -} - -export type BackupProgressEntry = BaseBackupProgressEntry - & OneOf<{ status: BackupProgressStatusEntry; summary: BackupProgressSummary }> - -export type BackupProgressStatusEntry = { - percentDone?: number - totalFiles?: string - totalBytes?: string - filesDone?: string - bytesDone?: string - currentFile?: string[] -} - -export type BackupProgressSummary = { - filesNew?: string - filesChanged?: string - filesUnmodified?: string - dirsNew?: string - dirsChanged?: string - dirsUnmodified?: string - dataBlobs?: string - treeBlobs?: string - dataAdded?: string - totalFilesProcessed?: string - totalBytesProcessed?: string - totalDuration?: number - snapshotId?: string -} - -export type RestoreProgressEntry = { - messageType?: string - secondsElapsed?: number - totalBytes?: string - bytesRestored?: string - totalFiles?: string - filesRestored?: string - percentDone?: number -} \ No newline at end of file diff --git a/webui/gen/ts/v1/restic_pb.ts b/webui/gen/ts/v1/restic_pb.ts new file mode 100644 index 00000000..5b565549 --- /dev/null +++ b/webui/gen/ts/v1/restic_pb.ts @@ -0,0 +1,445 @@ +// @generated by protoc-gen-es v1.6.0 with parameter "target=ts" +// @generated from file v1/restic.proto (package v1, syntax proto3) +/* eslint-disable */ +// @ts-nocheck + +import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; +import { Message, proto3, protoInt64 } from "@bufbuild/protobuf"; + +/** + * ResticSnapshot represents a restic snapshot. + * + * @generated from message v1.ResticSnapshot + */ +export class ResticSnapshot extends Message { + /** + * @generated from field: string id = 1; + */ + id = ""; + + /** + * @generated from field: int64 unix_time_ms = 2; + */ + unixTimeMs = protoInt64.zero; + + /** + * @generated from field: string hostname = 3; + */ + hostname = ""; + + /** + * @generated from field: string username = 4; + */ + username = ""; + + /** + * tree hash + * + * @generated from field: string tree = 5; + */ + tree = ""; + + /** + * parent snapshot's id + * + * @generated from field: string parent = 6; + */ + parent = ""; + + /** + * @generated from field: repeated string paths = 7; + */ + paths: string[] = []; + + /** + * @generated from field: repeated string tags = 8; + */ + tags: string[] = []; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.ResticSnapshot"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "unix_time_ms", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 3, name: "hostname", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 4, name: "username", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 5, name: "tree", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 6, name: "parent", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 7, name: "paths", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + { no: 8, name: "tags", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): ResticSnapshot { + return new ResticSnapshot().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): ResticSnapshot { + return new ResticSnapshot().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): ResticSnapshot { + return new ResticSnapshot().fromJsonString(jsonString, options); + } + + static equals(a: ResticSnapshot | PlainMessage | undefined, b: ResticSnapshot | PlainMessage | undefined): boolean { + return proto3.util.equals(ResticSnapshot, a, b); + } +} + +/** + * ResticSnapshotList represents a list of restic snapshots. + * + * @generated from message v1.ResticSnapshotList + */ +export class ResticSnapshotList extends Message { + /** + * @generated from field: repeated v1.ResticSnapshot snapshots = 1; + */ + snapshots: ResticSnapshot[] = []; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.ResticSnapshotList"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "snapshots", kind: "message", T: ResticSnapshot, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): ResticSnapshotList { + return new ResticSnapshotList().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): ResticSnapshotList { + return new ResticSnapshotList().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): ResticSnapshotList { + return new ResticSnapshotList().fromJsonString(jsonString, options); + } + + static equals(a: ResticSnapshotList | PlainMessage | undefined, b: ResticSnapshotList | PlainMessage | undefined): boolean { + return proto3.util.equals(ResticSnapshotList, a, b); + } +} + +/** + * BackupProgressEntriy represents a single entry in the backup progress stream. + * + * @generated from message v1.BackupProgressEntry + */ +export class BackupProgressEntry extends Message { + /** + * @generated from oneof v1.BackupProgressEntry.entry + */ + entry: { + /** + * @generated from field: v1.BackupProgressStatusEntry status = 1; + */ + value: BackupProgressStatusEntry; + case: "status"; + } | { + /** + * @generated from field: v1.BackupProgressSummary summary = 2; + */ + value: BackupProgressSummary; + case: "summary"; + } | { case: undefined; value?: undefined } = { case: undefined }; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.BackupProgressEntry"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "status", kind: "message", T: BackupProgressStatusEntry, oneof: "entry" }, + { no: 2, name: "summary", kind: "message", T: BackupProgressSummary, oneof: "entry" }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): BackupProgressEntry { + return new BackupProgressEntry().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): BackupProgressEntry { + return new BackupProgressEntry().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): BackupProgressEntry { + return new BackupProgressEntry().fromJsonString(jsonString, options); + } + + static equals(a: BackupProgressEntry | PlainMessage | undefined, b: BackupProgressEntry | PlainMessage | undefined): boolean { + return proto3.util.equals(BackupProgressEntry, a, b); + } +} + +/** + * BackupProgressStatusEntry represents a single status entry in the backup progress stream. + * + * @generated from message v1.BackupProgressStatusEntry + */ +export class BackupProgressStatusEntry extends Message { + /** + * 0.0 - 1.0 + * + * @generated from field: double percent_done = 1; + */ + percentDone = 0; + + /** + * @generated from field: int64 total_files = 2; + */ + totalFiles = protoInt64.zero; + + /** + * @generated from field: int64 total_bytes = 3; + */ + totalBytes = protoInt64.zero; + + /** + * @generated from field: int64 files_done = 4; + */ + filesDone = protoInt64.zero; + + /** + * @generated from field: int64 bytes_done = 5; + */ + bytesDone = protoInt64.zero; + + /** + * @generated from field: repeated string current_file = 6; + */ + currentFile: string[] = []; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.BackupProgressStatusEntry"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "percent_done", kind: "scalar", T: 1 /* ScalarType.DOUBLE */ }, + { no: 2, name: "total_files", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 3, name: "total_bytes", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 4, name: "files_done", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 5, name: "bytes_done", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 6, name: "current_file", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): BackupProgressStatusEntry { + return new BackupProgressStatusEntry().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): BackupProgressStatusEntry { + return new BackupProgressStatusEntry().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): BackupProgressStatusEntry { + return new BackupProgressStatusEntry().fromJsonString(jsonString, options); + } + + static equals(a: BackupProgressStatusEntry | PlainMessage | undefined, b: BackupProgressStatusEntry | PlainMessage | undefined): boolean { + return proto3.util.equals(BackupProgressStatusEntry, a, b); + } +} + +/** + * BackupProgressSummary represents a the summary event emitted at the end of a backup stream. + * + * @generated from message v1.BackupProgressSummary + */ +export class BackupProgressSummary extends Message { + /** + * @generated from field: int64 files_new = 1; + */ + filesNew = protoInt64.zero; + + /** + * @generated from field: int64 files_changed = 2; + */ + filesChanged = protoInt64.zero; + + /** + * @generated from field: int64 files_unmodified = 3; + */ + filesUnmodified = protoInt64.zero; + + /** + * @generated from field: int64 dirs_new = 4; + */ + dirsNew = protoInt64.zero; + + /** + * @generated from field: int64 dirs_changed = 5; + */ + dirsChanged = protoInt64.zero; + + /** + * @generated from field: int64 dirs_unmodified = 6; + */ + dirsUnmodified = protoInt64.zero; + + /** + * @generated from field: int64 data_blobs = 7; + */ + dataBlobs = protoInt64.zero; + + /** + * @generated from field: int64 tree_blobs = 8; + */ + treeBlobs = protoInt64.zero; + + /** + * @generated from field: int64 data_added = 9; + */ + dataAdded = protoInt64.zero; + + /** + * @generated from field: int64 total_files_processed = 10; + */ + totalFilesProcessed = protoInt64.zero; + + /** + * @generated from field: int64 total_bytes_processed = 11; + */ + totalBytesProcessed = protoInt64.zero; + + /** + * @generated from field: double total_duration = 12; + */ + totalDuration = 0; + + /** + * @generated from field: string snapshot_id = 13; + */ + snapshotId = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.BackupProgressSummary"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "files_new", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 2, name: "files_changed", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 3, name: "files_unmodified", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 4, name: "dirs_new", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 5, name: "dirs_changed", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 6, name: "dirs_unmodified", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 7, name: "data_blobs", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 8, name: "tree_blobs", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 9, name: "data_added", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 10, name: "total_files_processed", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 11, name: "total_bytes_processed", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 12, name: "total_duration", kind: "scalar", T: 1 /* ScalarType.DOUBLE */ }, + { no: 13, name: "snapshot_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): BackupProgressSummary { + return new BackupProgressSummary().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): BackupProgressSummary { + return new BackupProgressSummary().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): BackupProgressSummary { + return new BackupProgressSummary().fromJsonString(jsonString, options); + } + + static equals(a: BackupProgressSummary | PlainMessage | undefined, b: BackupProgressSummary | PlainMessage | undefined): boolean { + return proto3.util.equals(BackupProgressSummary, a, b); + } +} + +/** + * RestoreProgressEvent represents a single entry in the restore progress stream. + * + * @generated from message v1.RestoreProgressEntry + */ +export class RestoreProgressEntry extends Message { + /** + * "summary" or "status" + * + * @generated from field: string message_type = 1; + */ + messageType = ""; + + /** + * @generated from field: double seconds_elapsed = 2; + */ + secondsElapsed = 0; + + /** + * @generated from field: int64 total_bytes = 3; + */ + totalBytes = protoInt64.zero; + + /** + * @generated from field: int64 bytes_restored = 4; + */ + bytesRestored = protoInt64.zero; + + /** + * @generated from field: int64 total_files = 5; + */ + totalFiles = protoInt64.zero; + + /** + * @generated from field: int64 files_restored = 6; + */ + filesRestored = protoInt64.zero; + + /** + * 0.0 - 1.0 + * + * @generated from field: double percent_done = 7; + */ + percentDone = 0; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.RestoreProgressEntry"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "message_type", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "seconds_elapsed", kind: "scalar", T: 1 /* ScalarType.DOUBLE */ }, + { no: 3, name: "total_bytes", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 4, name: "bytes_restored", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 5, name: "total_files", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 6, name: "files_restored", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 7, name: "percent_done", kind: "scalar", T: 1 /* ScalarType.DOUBLE */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): RestoreProgressEntry { + return new RestoreProgressEntry().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): RestoreProgressEntry { + return new RestoreProgressEntry().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): RestoreProgressEntry { + return new RestoreProgressEntry().fromJsonString(jsonString, options); + } + + static equals(a: RestoreProgressEntry | PlainMessage | undefined, b: RestoreProgressEntry | PlainMessage | undefined): boolean { + return proto3.util.equals(RestoreProgressEntry, a, b); + } +} + diff --git a/webui/gen/ts/v1/service.pb.ts b/webui/gen/ts/v1/service.pb.ts deleted file mode 100644 index 989ea70c..00000000 --- a/webui/gen/ts/v1/service.pb.ts +++ /dev/null @@ -1,110 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck -/* -* This file is a generated Typescript file for GRPC Gateway, DO NOT MODIFY -*/ - -import * as fm from "../fetch.pb" -import * as GoogleProtobufEmpty from "../google/protobuf/empty.pb" -import * as TypesValue from "../types/value.pb" -import * as V1Config from "./config.pb" -import * as V1Operations from "./operations.pb" -import * as V1Restic from "./restic.pb" -export type ClearHistoryRequest = { - repoId?: string - planId?: string - onlyFailed?: boolean -} - -export type ListSnapshotsRequest = { - repoId?: string - planId?: string -} - -export type GetOperationsRequest = { - repoId?: string - planId?: string - snapshotId?: string - ids?: string[] - lastN?: string -} - -export type RestoreSnapshotRequest = { - repoId?: string - planId?: string - snapshotId?: string - path?: string - target?: string -} - -export type ListSnapshotFilesRequest = { - repoId?: string - snapshotId?: string - path?: string -} - -export type ListSnapshotFilesResponse = { - path?: string - entries?: LsEntry[] -} - -export type LsEntry = { - name?: string - type?: string - path?: string - uid?: string - gid?: string - size?: string - mode?: string - mtime?: string - atime?: string - ctime?: string -} - -export class Backrest { - static GetConfig(req: GoogleProtobufEmpty.Empty, initReq?: fm.InitReq): Promise { - return fm.fetchReq(`/v1/config?${fm.renderURLSearchParams(req, [])}`, {...initReq, method: "GET"}) - } - static SetConfig(req: V1Config.Config, initReq?: fm.InitReq): Promise { - return fm.fetchReq(`/v1/config`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)}) - } - static AddRepo(req: V1Config.Repo, initReq?: fm.InitReq): Promise { - return fm.fetchReq(`/v1/config/repo`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)}) - } - static GetOperationEvents(req: GoogleProtobufEmpty.Empty, entityNotifier?: fm.NotifyStreamEntityArrival, initReq?: fm.InitReq): Promise { - return fm.fetchStreamingRequest(`/v1/events/operations?${fm.renderURLSearchParams(req, [])}`, entityNotifier, {...initReq, method: "GET"}) - } - static GetOperations(req: GetOperationsRequest, initReq?: fm.InitReq): Promise { - return fm.fetchReq(`/v1/operations`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)}) - } - static ListSnapshots(req: ListSnapshotsRequest, initReq?: fm.InitReq): Promise { - return fm.fetchReq(`/v1/snapshots`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)}) - } - static ListSnapshotFiles(req: ListSnapshotFilesRequest, initReq?: fm.InitReq): Promise { - return fm.fetchReq(`/v1/snapshots/files`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)}) - } - static Backup(req: TypesValue.StringValue, initReq?: fm.InitReq): Promise { - return fm.fetchReq(`/v1/cmd/backup`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)}) - } - static Prune(req: TypesValue.StringValue, initReq?: fm.InitReq): Promise { - return fm.fetchReq(`/v1/cmd/prune`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)}) - } - static Forget(req: TypesValue.StringValue, initReq?: fm.InitReq): Promise { - return fm.fetchReq(`/v1/cmd/forget`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)}) - } - static Restore(req: RestoreSnapshotRequest, initReq?: fm.InitReq): Promise { - return fm.fetchReq(`/v1/cmd/restore`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)}) - } - static Unlock(req: TypesValue.StringValue, initReq?: fm.InitReq): Promise { - return fm.fetchReq(`/v1/cmd/unlock`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)}) - } - static Cancel(req: TypesValue.Int64Value, initReq?: fm.InitReq): Promise { - return fm.fetchReq(`/v1/cmd/cancel`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)}) - } - static ClearHistory(req: ClearHistoryRequest, initReq?: fm.InitReq): Promise { - return fm.fetchReq(`/v1/cmd/clear_history`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)}) - } - static PathAutocomplete(req: TypesValue.StringValue, initReq?: fm.InitReq): Promise { - return fm.fetchReq(`/v1/autocomplete/path`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)}) - } -} \ No newline at end of file diff --git a/webui/gen/ts/v1/service_connect.ts b/webui/gen/ts/v1/service_connect.ts new file mode 100644 index 00000000..8fc65d6f --- /dev/null +++ b/webui/gen/ts/v1/service_connect.ts @@ -0,0 +1,170 @@ +// @generated by protoc-gen-connect-es v1.2.0 with parameter "target=ts" +// @generated from file v1/service.proto (package v1, syntax proto3) +/* eslint-disable */ +// @ts-nocheck + +import { Empty, MethodKind } from "@bufbuild/protobuf"; +import { Config, Repo } from "./config_pb.js"; +import { OperationEvent, OperationList } from "./operations_pb.js"; +import { ClearHistoryRequest, GetOperationsRequest, ListSnapshotFilesRequest, ListSnapshotFilesResponse, ListSnapshotsRequest, RestoreSnapshotRequest } from "./service_pb.js"; +import { ResticSnapshotList } from "./restic_pb.js"; +import { Int64Value, StringList, StringValue } from "../types/value_pb.js"; + +/** + * @generated from service v1.Backrest + */ +export const Backrest = { + typeName: "v1.Backrest", + methods: { + /** + * @generated from rpc v1.Backrest.GetConfig + */ + getConfig: { + name: "GetConfig", + I: Empty, + O: Config, + kind: MethodKind.Unary, + }, + /** + * @generated from rpc v1.Backrest.SetConfig + */ + setConfig: { + name: "SetConfig", + I: Config, + O: Config, + kind: MethodKind.Unary, + }, + /** + * @generated from rpc v1.Backrest.AddRepo + */ + addRepo: { + name: "AddRepo", + I: Repo, + O: Config, + kind: MethodKind.Unary, + }, + /** + * @generated from rpc v1.Backrest.GetOperationEvents + */ + getOperationEvents: { + name: "GetOperationEvents", + I: Empty, + O: OperationEvent, + kind: MethodKind.ServerStreaming, + }, + /** + * @generated from rpc v1.Backrest.GetOperations + */ + getOperations: { + name: "GetOperations", + I: GetOperationsRequest, + O: OperationList, + kind: MethodKind.Unary, + }, + /** + * @generated from rpc v1.Backrest.ListSnapshots + */ + listSnapshots: { + name: "ListSnapshots", + I: ListSnapshotsRequest, + O: ResticSnapshotList, + kind: MethodKind.Unary, + }, + /** + * @generated from rpc v1.Backrest.ListSnapshotFiles + */ + listSnapshotFiles: { + name: "ListSnapshotFiles", + I: ListSnapshotFilesRequest, + O: ListSnapshotFilesResponse, + kind: MethodKind.Unary, + }, + /** + * Backup schedules a backup operation. It accepts a plan id and returns empty if the task is enqueued. + * + * @generated from rpc v1.Backrest.Backup + */ + backup: { + name: "Backup", + I: StringValue, + O: Empty, + kind: MethodKind.Unary, + }, + /** + * Prune schedules a prune operation. + * + * @generated from rpc v1.Backrest.Prune + */ + prune: { + name: "Prune", + I: StringValue, + O: Empty, + kind: MethodKind.Unary, + }, + /** + * Forget schedules a forget operation. + * + * @generated from rpc v1.Backrest.Forget + */ + forget: { + name: "Forget", + I: StringValue, + O: Empty, + kind: MethodKind.Unary, + }, + /** + * Restore schedules a restore operation. + * + * @generated from rpc v1.Backrest.Restore + */ + restore: { + name: "Restore", + I: RestoreSnapshotRequest, + O: Empty, + kind: MethodKind.Unary, + }, + /** + * Unlock synchronously attempts to unlock the repo. Will block if other operations are in progress. + * + * @generated from rpc v1.Backrest.Unlock + */ + unlock: { + name: "Unlock", + I: StringValue, + O: Empty, + kind: MethodKind.Unary, + }, + /** + * Cancel attempts to cancel a task with the given operation ID. Not guaranteed to succeed. + * + * @generated from rpc v1.Backrest.Cancel + */ + cancel: { + name: "Cancel", + I: Int64Value, + O: Empty, + kind: MethodKind.Unary, + }, + /** + * @generated from rpc v1.Backrest.ClearHistory + */ + clearHistory: { + name: "ClearHistory", + I: ClearHistoryRequest, + O: Empty, + kind: MethodKind.Unary, + }, + /** + * PathAutocomplete provides path autocompletion options for a given filesystem path. + * + * @generated from rpc v1.Backrest.PathAutocomplete + */ + pathAutocomplete: { + name: "PathAutocomplete", + I: StringValue, + O: StringList, + kind: MethodKind.Unary, + }, + } +} as const; + diff --git a/webui/gen/ts/v1/service_pb.ts b/webui/gen/ts/v1/service_pb.ts new file mode 100644 index 00000000..83f2e20f --- /dev/null +++ b/webui/gen/ts/v1/service_pb.ts @@ -0,0 +1,407 @@ +// @generated by protoc-gen-es v1.6.0 with parameter "target=ts" +// @generated from file v1/service.proto (package v1, syntax proto3) +/* eslint-disable */ +// @ts-nocheck + +import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; +import { Message, proto3, protoInt64 } from "@bufbuild/protobuf"; + +/** + * @generated from message v1.ClearHistoryRequest + */ +export class ClearHistoryRequest extends Message { + /** + * @generated from field: string repo_id = 1; + */ + repoId = ""; + + /** + * @generated from field: string plan_id = 2; + */ + planId = ""; + + /** + * @generated from field: bool only_failed = 3; + */ + onlyFailed = false; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.ClearHistoryRequest"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "repo_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "plan_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 3, name: "only_failed", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): ClearHistoryRequest { + return new ClearHistoryRequest().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): ClearHistoryRequest { + return new ClearHistoryRequest().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): ClearHistoryRequest { + return new ClearHistoryRequest().fromJsonString(jsonString, options); + } + + static equals(a: ClearHistoryRequest | PlainMessage | undefined, b: ClearHistoryRequest | PlainMessage | undefined): boolean { + return proto3.util.equals(ClearHistoryRequest, a, b); + } +} + +/** + * @generated from message v1.ListSnapshotsRequest + */ +export class ListSnapshotsRequest extends Message { + /** + * @generated from field: string repo_id = 1; + */ + repoId = ""; + + /** + * @generated from field: string plan_id = 2; + */ + planId = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.ListSnapshotsRequest"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "repo_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "plan_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): ListSnapshotsRequest { + return new ListSnapshotsRequest().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): ListSnapshotsRequest { + return new ListSnapshotsRequest().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): ListSnapshotsRequest { + return new ListSnapshotsRequest().fromJsonString(jsonString, options); + } + + static equals(a: ListSnapshotsRequest | PlainMessage | undefined, b: ListSnapshotsRequest | PlainMessage | undefined): boolean { + return proto3.util.equals(ListSnapshotsRequest, a, b); + } +} + +/** + * @generated from message v1.GetOperationsRequest + */ +export class GetOperationsRequest extends Message { + /** + * @generated from field: string repo_id = 1; + */ + repoId = ""; + + /** + * @generated from field: string plan_id = 2; + */ + planId = ""; + + /** + * @generated from field: string snapshot_id = 4; + */ + snapshotId = ""; + + /** + * @generated from field: repeated int64 ids = 5; + */ + ids: bigint[] = []; + + /** + * limit to the last n operations + * + * @generated from field: int64 last_n = 3; + */ + lastN = protoInt64.zero; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.GetOperationsRequest"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "repo_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "plan_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 4, name: "snapshot_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 5, name: "ids", kind: "scalar", T: 3 /* ScalarType.INT64 */, repeated: true }, + { no: 3, name: "last_n", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): GetOperationsRequest { + return new GetOperationsRequest().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): GetOperationsRequest { + return new GetOperationsRequest().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): GetOperationsRequest { + return new GetOperationsRequest().fromJsonString(jsonString, options); + } + + static equals(a: GetOperationsRequest | PlainMessage | undefined, b: GetOperationsRequest | PlainMessage | undefined): boolean { + return proto3.util.equals(GetOperationsRequest, a, b); + } +} + +/** + * @generated from message v1.RestoreSnapshotRequest + */ +export class RestoreSnapshotRequest extends Message { + /** + * @generated from field: string repo_id = 1; + */ + repoId = ""; + + /** + * @generated from field: string plan_id = 2; + */ + planId = ""; + + /** + * @generated from field: string snapshot_id = 3; + */ + snapshotId = ""; + + /** + * @generated from field: string path = 4; + */ + path = ""; + + /** + * @generated from field: string target = 5; + */ + target = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.RestoreSnapshotRequest"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "repo_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "plan_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 3, name: "snapshot_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 4, name: "path", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 5, name: "target", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): RestoreSnapshotRequest { + return new RestoreSnapshotRequest().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): RestoreSnapshotRequest { + return new RestoreSnapshotRequest().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): RestoreSnapshotRequest { + return new RestoreSnapshotRequest().fromJsonString(jsonString, options); + } + + static equals(a: RestoreSnapshotRequest | PlainMessage | undefined, b: RestoreSnapshotRequest | PlainMessage | undefined): boolean { + return proto3.util.equals(RestoreSnapshotRequest, a, b); + } +} + +/** + * @generated from message v1.ListSnapshotFilesRequest + */ +export class ListSnapshotFilesRequest extends Message { + /** + * @generated from field: string repo_id = 1; + */ + repoId = ""; + + /** + * @generated from field: string snapshot_id = 2; + */ + snapshotId = ""; + + /** + * @generated from field: string path = 3; + */ + path = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.ListSnapshotFilesRequest"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "repo_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "snapshot_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 3, name: "path", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): ListSnapshotFilesRequest { + return new ListSnapshotFilesRequest().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): ListSnapshotFilesRequest { + return new ListSnapshotFilesRequest().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): ListSnapshotFilesRequest { + return new ListSnapshotFilesRequest().fromJsonString(jsonString, options); + } + + static equals(a: ListSnapshotFilesRequest | PlainMessage | undefined, b: ListSnapshotFilesRequest | PlainMessage | undefined): boolean { + return proto3.util.equals(ListSnapshotFilesRequest, a, b); + } +} + +/** + * @generated from message v1.ListSnapshotFilesResponse + */ +export class ListSnapshotFilesResponse extends Message { + /** + * @generated from field: string path = 1; + */ + path = ""; + + /** + * @generated from field: repeated v1.LsEntry entries = 2; + */ + entries: LsEntry[] = []; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.ListSnapshotFilesResponse"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "path", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "entries", kind: "message", T: LsEntry, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): ListSnapshotFilesResponse { + return new ListSnapshotFilesResponse().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): ListSnapshotFilesResponse { + return new ListSnapshotFilesResponse().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): ListSnapshotFilesResponse { + return new ListSnapshotFilesResponse().fromJsonString(jsonString, options); + } + + static equals(a: ListSnapshotFilesResponse | PlainMessage | undefined, b: ListSnapshotFilesResponse | PlainMessage | undefined): boolean { + return proto3.util.equals(ListSnapshotFilesResponse, a, b); + } +} + +/** + * @generated from message v1.LsEntry + */ +export class LsEntry extends Message { + /** + * @generated from field: string name = 1; + */ + name = ""; + + /** + * @generated from field: string type = 2; + */ + type = ""; + + /** + * @generated from field: string path = 3; + */ + path = ""; + + /** + * @generated from field: int64 uid = 4; + */ + uid = protoInt64.zero; + + /** + * @generated from field: int64 gid = 5; + */ + gid = protoInt64.zero; + + /** + * @generated from field: int64 size = 6; + */ + size = protoInt64.zero; + + /** + * @generated from field: int64 mode = 7; + */ + mode = protoInt64.zero; + + /** + * @generated from field: string mtime = 8; + */ + mtime = ""; + + /** + * @generated from field: string atime = 9; + */ + atime = ""; + + /** + * @generated from field: string ctime = 10; + */ + ctime = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "v1.LsEntry"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "type", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 3, name: "path", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 4, name: "uid", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 5, name: "gid", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 6, name: "size", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 7, name: "mode", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 8, name: "mtime", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 9, name: "atime", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 10, name: "ctime", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): LsEntry { + return new LsEntry().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): LsEntry { + return new LsEntry().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): LsEntry { + return new LsEntry().fromJsonString(jsonString, options); + } + + static equals(a: LsEntry | PlainMessage | undefined, b: LsEntry | PlainMessage | undefined): boolean { + return proto3.util.equals(LsEntry, a, b); + } +} + diff --git a/webui/package-lock.json b/webui/package-lock.json index cd5d2995..9b9c3f66 100644 --- a/webui/package-lock.json +++ b/webui/package-lock.json @@ -10,6 +10,9 @@ "license": "ISC", "dependencies": { "@ant-design/icons": "^5.2.6", + "@bufbuild/protobuf": "^1.6.0", + "@connectrpc/connect": "^1.2.0", + "@connectrpc/connect-web": "^1.2.0", "@types/lodash": "^4.14.202", "@types/node": "^20.9.0", "@types/react": "^18.2.37", @@ -252,6 +255,28 @@ "node": ">=6.9.0" } }, + "node_modules/@bufbuild/protobuf": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-1.6.0.tgz", + "integrity": "sha512-hp19vSFgNw3wBBcVBx5qo5pufCqjaJ0Cfk5H/pfjNOfNWU+4/w0QVOmfAOZNRrNWRrVuaJWxcN8P2vhOkkzbBQ==" + }, + "node_modules/@connectrpc/connect": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@connectrpc/connect/-/connect-1.2.0.tgz", + "integrity": "sha512-kHF30xAlXF2Y7S1I7XN/D3psKLfjxitgNRmF093KNP+cE9yAnqDAGop6aby3Z5k4XQw2ebjeX4E41db7R3FzaQ==", + "peerDependencies": { + "@bufbuild/protobuf": "^1.4.2" + } + }, + "node_modules/@connectrpc/connect-web": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@connectrpc/connect-web/-/connect-web-1.2.0.tgz", + "integrity": "sha512-vjFKTP/AzSnC8JvkGKRgpggZIB0v+Lv7U+/Tb/pRNGZI0WSElhGDXWgIn3xfcSNQWi079m45c5MlikszzIRsYg==", + "peerDependencies": { + "@bufbuild/protobuf": "^1.4.2", + "@connectrpc/connect": "1.2.0" + } + }, "node_modules/@ctrl/tinycolor": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", diff --git a/webui/package.json b/webui/package.json index 2f6cc81b..63c23010 100644 --- a/webui/package.json +++ b/webui/package.json @@ -6,12 +6,16 @@ "start": "parcel serve src/index.html", "build": "BACKREST_BUILD_VERSION=$(git describe --tags --abbrev=0) UI_OS=unix parcel build src/index.html", "build-windows": "set UI_OS=windows & parcel build src/index.html", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "check": "tsc --noEmit" }, "author": "", "license": "ISC", "dependencies": { "@ant-design/icons": "^5.2.6", + "@bufbuild/protobuf": "^1.6.0", + "@connectrpc/connect": "^1.2.0", + "@connectrpc/connect-web": "^1.2.0", "@types/lodash": "^4.14.202", "@types/node": "^20.9.0", "@types/react": "^18.2.37", diff --git a/webui/src/api.ts b/webui/src/api.ts new file mode 100644 index 00000000..7e27a4fc --- /dev/null +++ b/webui/src/api.ts @@ -0,0 +1,10 @@ +import { useMemo } from "react"; +import { createConnectTransport } from "@connectrpc/connect-web"; +import { createPromiseClient, PromiseClient } from "@connectrpc/connect"; +import { Backrest } from "../gen/ts/v1/service_connect"; + +const transport = createConnectTransport({ + baseUrl: "/", +}); + +export const backrestService = createPromiseClient(Backrest, transport); diff --git a/webui/src/components/ActivityBar.tsx b/webui/src/components/ActivityBar.tsx index 83c22c57..81d0e1a2 100644 --- a/webui/src/components/ActivityBar.tsx +++ b/webui/src/components/ActivityBar.tsx @@ -1,10 +1,10 @@ import React, { useEffect, useState } from "react"; -import { EOperation, detailsForOperation, displayTypeToString, getTypeForDisplay, subscribeToOperations, toEop, unsubscribeFromOperations } from "../state/oplog"; -import { OperationEvent, OperationStatus } from "../../gen/ts/v1/operations.pb"; +import { detailsForOperation, displayTypeToString, getTypeForDisplay, subscribeToOperations, unsubscribeFromOperations } from "../state/oplog"; import { formatDuration } from "../lib/formatting"; +import { Operation, OperationEvent, OperationStatus } from "../../gen/ts/v1/operations_pb"; export const ActivityBar = () => { - const [activeOperations, setActiveOperations] = useState([]); + const [activeOperations, setActiveOperations] = useState([]); useEffect(() => { const callback = ({ operation, type }: OperationEvent) => { @@ -13,9 +13,9 @@ export const ActivityBar = () => { setActiveOperations((ops) => { ops = ops.filter((op) => op.id !== operation.id); if (operation.status === OperationStatus.STATUS_INPROGRESS) { - ops.push(toEop(operation)); + ops.push(operation); } - ops.sort((a, b) => b.parsedTime - a.parsedTime); + ops.sort((a, b) => Number(b.unixTimeStartMs - a.unixTimeStartMs)); return ops; }); } diff --git a/webui/src/components/ModalManager.tsx b/webui/src/components/ModalManager.tsx index e19da5bd..0cab7ec9 100644 --- a/webui/src/components/ModalManager.tsx +++ b/webui/src/components/ModalManager.tsx @@ -1,4 +1,3 @@ -import { Spin } from "antd"; import React, { useContext } from "react"; import { createContext } from "react"; diff --git a/webui/src/components/OperationList.tsx b/webui/src/components/OperationList.tsx index 2f32b650..0f4c862c 100644 --- a/webui/src/components/OperationList.tsx +++ b/webui/src/components/OperationList.tsx @@ -4,7 +4,7 @@ import { OperationEvent, OperationEventType, OperationStatus, -} from "../../gen/ts/v1/operations.pb"; +} from "../../gen/ts/v1/operations_pb"; import { Button, Card, @@ -22,19 +22,17 @@ import { DeleteOutlined, DownloadOutlined, } from "@ant-design/icons"; -import { BackupProgressEntry, ResticSnapshot } from "../../gen/ts/v1/restic.pb"; +import { BackupProgressEntry, ResticSnapshot } from "../../gen/ts/v1/restic_pb"; import { BackupInfo, BackupInfoCollector, DisplayType, - EOperation, detailsForOperation, displayTypeToString, getOperations, getTypeForDisplay, shouldHideStatus, subscribeToOperations, - toEop, unsubscribeFromOperations, } from "../state/oplog"; import { SnapshotBrowser } from "./SnapshotBrowser"; @@ -44,9 +42,10 @@ import { normalizeSnapshotId, } from "../lib/formatting"; import _ from "lodash"; -import { GetOperationsRequest, Backrest } from "../../gen/ts/v1/service.pb"; +import { GetOperationsRequest } from "../../gen/ts/v1/service_pb"; import { useAlertApi } from "./Alerts"; import { MessageInstance } from "antd/es/message/interface"; +import { backrestService } from "../api"; export const OperationList = ({ req, @@ -134,7 +133,7 @@ export const OperationList = ({ if (shouldHideStatus(op.status!)) { return null; } - return + return })} ); @@ -152,7 +151,7 @@ export const OperationRow = ({ operation, alertApi, showPlan, -}: React.PropsWithoutRef<{ operation: EOperation, alertApi?: MessageInstance, showPlan: boolean }>) => { +}: React.PropsWithoutRef<{ operation: Operation, alertApi?: MessageInstance, showPlan: boolean }>) => { const details = detailsForOperation(operation); const displayType = getTypeForDisplay(operation); let avatar: React.ReactNode; @@ -187,7 +186,7 @@ export const OperationRow = ({ const opName = displayTypeToString(getTypeForDisplay(operation)); let title = ( <> - {showPlan ? operation.planId + " - " : undefined} {formatTime(operation.unixTimeStartMs!)} - {opName}{" "} + {showPlan ? operation.planId + " - " : undefined} {formatTime(Number(operation.unixTimeStartMs))} - {opName}{" "} {details.displayState} ); @@ -196,9 +195,11 @@ export const OperationRow = ({ title = <> {title} } @@ -210,8 +211,8 @@ export const OperationRow = ({ operation.status === OperationStatus.STATUS_ERROR ) { body =
{operation.displayMessage}
; - } else if (operation.operationBackup) { - const backupOp = operation.operationBackup; + } else if (operation.op.case === "operationBackup") { + const backupOp = operation.op.value; body = ( <> ); - } else if (operation.operationIndexSnapshot) { - const snapshotOp = operation.operationIndexSnapshot; + } else if (operation.op.case === "operationIndexSnapshot") { + const snapshotOp = operation.op.value; body = ( ); - } else if (operation.operationForget) { - const forgetOp = operation.operationForget; + } else if (operation.op.case === "operationForget") { + const forgetOp = operation.op.value; if (forgetOp.forget?.length === 0) { return null; } @@ -278,7 +279,7 @@ export const OperationRow = ({ Removed snapshots:
{forgetOp.forget?.map((f) => (
                   
- {"removed snapshot " + normalizeSnapshotId(f.id!) + " taken at " + formatTime(f.unixTimeMs!)}
+ {"removed snapshot " + normalizeSnapshotId(f.id!) + " taken at " + formatTime(Number(f.unixTimeMs))}
))}
Policy: @@ -293,8 +294,8 @@ export const OperationRow = ({ /> ); - } else if (operation.operationPrune) { - const prune = operation.operationPrune; + } else if (operation.op.case === "operationPrune") { + const prune = operation.op.value; body = ( ); - } else if (operation.operationRestore) { - const restore = operation.operationRestore; + } else if (operation.op.case === "operationRestore") { + const restore = operation.op.value; body = ( <> Restore {restore.path} to {restore.target} @@ -395,11 +396,11 @@ const BackupOperationStatus = ({ return <>No status yet.; } - if (status.status) { - const st = status.status; + if (status.entry.case === "status") { + const st = status.entry.value; const progress = Math.round( - (parseInt(st.bytesDone!) / Math.max(parseInt(st.totalBytes!), 1)) * 1000 + (Number(st.bytesDone) / Math.max(Number(st.totalBytes), 1)) * 1000 ) / 10; return ( <> @@ -412,18 +413,18 @@ const BackupOperationStatus = ({ Bytes Done/Total
- {formatBytes(st.bytesDone)}/{formatBytes(st.totalBytes)} + {formatBytes(Number(st.bytesDone))}/{formatBytes(Number(st.totalBytes))} Files Done/Total
- {st.filesDone}/{st.totalFiles} + {Number(st.filesDone)}/{Number(st.totalFiles)} ); - } else if (status.summary) { - const sum = status.summary; + } else if (status.entry.case === "summary") { + const sum = status.entry.value; return ( <> @@ -434,34 +435,34 @@ const BackupOperationStatus = ({ Files Added
- {sum.filesNew} + {sum.filesNew.toString()} Files Changed
- {sum.filesChanged} + {sum.filesChanged.toString()} Files Unmodified
- {sum.filesChanged} + {sum.filesUnmodified.toString()} Bytes Added
- {formatBytes(sum.dataAdded)} + {formatBytes(Number(sum.dataAdded))} Total Bytes Processed
- {formatBytes(sum.totalBytesProcessed)} + {formatBytes(Number(sum.totalBytesProcessed))} Total Files Processed
- {sum.totalFilesProcessed} + {sum.totalFilesProcessed.toString()}
@@ -471,15 +472,3 @@ const BackupOperationStatus = ({ return <>No fields set. This shouldn't happen; } }; - -const getSnapshotId = (op: EOperation): string | null => { - if (op.operationBackup) { - const ob = op.operationBackup; - if (ob.lastStatus && ob.lastStatus.summary) { - return normalizeSnapshotId(ob.lastStatus.summary.snapshotId!); - } - } else if (op.operationIndexSnapshot) { - return normalizeSnapshotId(op.operationIndexSnapshot.snapshot!.id!); - } - return null; -}; diff --git a/webui/src/components/OperationTree.tsx b/webui/src/components/OperationTree.tsx index 906c7a3d..90e9e92f 100644 --- a/webui/src/components/OperationTree.tsx +++ b/webui/src/components/OperationTree.tsx @@ -2,8 +2,9 @@ import React, { useEffect, useMemo, useState } from "react"; import { BackupInfo, BackupInfoCollector, + displayTypeToString, getOperations, - shouldHideStatus, + getTypeForDisplay, subscribeToOperations, unsubscribeFromOperations, } from "../state/oplog"; @@ -23,10 +24,10 @@ import { QuestionOutlined, SaveOutlined, } from "@ant-design/icons"; -import { OperationEvent, OperationEventType, OperationStatus } from "../../gen/ts/v1/operations.pb"; +import { OperationEvent, OperationEventType, OperationStatus } from "../../gen/ts/v1/operations_pb"; import { useAlertApi } from "./Alerts"; import { OperationList } from "./OperationList"; -import { GetOperationsRequest } from "../../gen/ts/v1/service.pb"; +import { GetOperationsRequest } from "../../gen/ts/v1/service_pb"; type OpTreeNode = DataNode & { backup?: BackupInfo; @@ -114,7 +115,7 @@ export const OperationTree = ({ treeData={treeData} showIcon - defaultExpandedKeys={[backups[0].id!]} + defaultExpandedKeys={backups.slice(0, Math.min(5, backups.length)).map((b) => b.id!)} onSelect={(keys, info) => { if (info.selectedNodes.length === 0) return; const backup = info.selectedNodes[0].backup; @@ -132,15 +133,6 @@ export const OperationTree = ({ const b = node.backup; const details: string[] = []; - if (b.operations.length === 1) { - if (b.operations[0].operationForget) { - return <>Forget {formatTime(b.displayTime)}; - } - if (b.operations[0].operationPrune) { - return <>Prune {formatTime(b.displayTime)}; - } - } - if (b.status === OperationStatus.STATUS_PENDING) { details.push("scheduled, waiting"); } else if (b.status === OperationStatus.STATUS_SYSTEM_CANCELLED) { @@ -150,27 +142,25 @@ export const OperationTree = ({ } if (b.backupLastStatus) { - if (b.backupLastStatus.summary) { - const s = b.backupLastStatus.summary; + if (b.backupLastStatus.entry.case === "summary") { + const s = b.backupLastStatus.entry.value; details.push( - `${formatBytes(s.totalBytesProcessed)} in ${formatDuration( + `${formatBytes(Number(s.totalBytesProcessed))} in ${formatDuration( s.totalDuration! * 1000.0 // convert to ms )}` ); - } else if (b.backupLastStatus.status) { - const s = b.backupLastStatus.status; - const bytesDone = parseInt(s.bytesDone!); - const bytesTotal = parseInt(s.totalBytes!); - const percent = Math.floor((bytesDone / bytesTotal) * 100); + } else if (b.backupLastStatus.entry.case === "status") { + const s = b.backupLastStatus.entry.value; + const percent = Math.floor((Number(s.bytesDone) / Number(s.totalBytes)) * 100); details.push( `${percent}% processed ${formatBytes( - bytesDone - )} / ${formatBytes(bytesTotal)}` + Number(s.bytesDone) + )} / ${formatBytes(Number(s.totalBytes))}` ); } } if (b.snapshotInfo) { - details.push(`ID: ${normalizeSnapshotId(b.snapshotInfo.id!)}`); + details.push(`ID: ${normalizeSnapshotId(b.snapshotInfo.id)}`); } let detailsElem: React.ReactNode | null = null; @@ -182,9 +172,10 @@ export const OperationTree = ({ ); } + const type = getTypeForDisplay(b.operations[0]); return ( <> - Backup {formatTime(b.displayTime)} {detailsElem} + {displayTypeToString(type)} {formatTime(b.displayTime)} {detailsElem} ); } diff --git a/webui/src/components/SnapshotBrowser.tsx b/webui/src/components/SnapshotBrowser.tsx index 5bd919ef..f76b6553 100644 --- a/webui/src/components/SnapshotBrowser.tsx +++ b/webui/src/components/SnapshotBrowser.tsx @@ -4,9 +4,8 @@ import type { DataNode, EventDataNode } from "antd/es/tree"; import { ListSnapshotFilesResponse, LsEntry, - Backrest, RestoreSnapshotRequest, -} from "../../gen/ts/v1/service.pb"; +} from "../../gen/ts/v1/service_pb"; import { useAlertApi } from "./Alerts"; import { DownloadOutlined, @@ -17,6 +16,7 @@ import { useShowModal } from "./ModalManager"; import { formatBytes, normalizeSnapshotId } from "../lib/formatting"; import { URIAutocomplete } from "./URIAutocomplete"; import { validateForm } from "../lib/formutil"; +import { backrestService } from "../api"; const SnapshotBrowserContext = React.createContext<{ snapshotId: string; @@ -81,14 +81,11 @@ export const SnapshotBrowser = ({ useEffect(() => { (async () => { try { - const resp = await Backrest.ListSnapshotFiles( - { - path: "/", - repoId, - snapshotId, - }, - { pathPrefix: "/api" } - ); + const resp = await backrestService.listSnapshotFiles({ + path: "/", + repoId, + snapshotId, + }); setTreeData(respToNodes(resp)); } catch (e: any) { alertApi?.error("Failed to list snapshot files: " + e.message); @@ -101,14 +98,11 @@ export const SnapshotBrowser = ({ return; } - const resp = await Backrest.ListSnapshotFiles( - { - path: (key + "/") as string, - repoId, - snapshotId, - }, - { pathPrefix: "/api" } - ); + const resp = await backrestService.listSnapshotFiles({ + path: (key + "/") as string, + repoId, + snapshotId, + }); setTreeData((treeData) => { let toUpdate: DataNode | null = null; @@ -166,8 +160,6 @@ const respToNodes = (resp: ListSnapshotFilesResponse): DataNode[] => { return node; }); - console.log(JSON.stringify(nodes, null, 2)); - return nodes; }; @@ -226,7 +218,7 @@ const FileNode = ({ entry }: { entry: LsEntry }) => { {entry.name} {entry.type === "file" ? ( - ({formatBytes(entry.size)}) + ({formatBytes(Number(entry.size))}) ) : null} {dropdown} @@ -266,17 +258,13 @@ const RestoreModal = ({ setConfirmLoading(true); try { const values = await validateForm(form); - - await Backrest.Restore( - { - planId, - repoId, - snapshotId, - path, - target: values.target, - }, - { pathPrefix: "/api" } - ); + await backrestService.restore({ + planId, + repoId, + snapshotId, + path, + target: values.target, + }); } catch (e: any) { alert("Failed to restore snapshot: " + e.message); } finally { @@ -330,5 +318,3 @@ const RestoreModal = ({ ); }; - -const restoreFlow = (repoId: string, snapshotId: string, path: string) => { }; diff --git a/webui/src/components/URIAutocomplete.tsx b/webui/src/components/URIAutocomplete.tsx index e2f24c62..c4e0cd31 100644 --- a/webui/src/components/URIAutocomplete.tsx +++ b/webui/src/components/URIAutocomplete.tsx @@ -1,10 +1,10 @@ import { AutoComplete } from "antd"; import React, { useEffect, useState } from "react"; -import { Backrest } from "../../gen/ts/v1/service.pb"; -import { StringList } from "../../gen/ts/types/value.pb"; +import { StringList } from "../../gen/ts/types/value_pb"; import { isWindows } from "../state/buildcfg"; +import { backrestService } from "../api"; +import _ from "lodash"; -let timeout: NodeJS.Timeout | undefined = undefined; const sep = isWindows ? "\\" : "/"; export const URIAutocomplete = (props: React.PropsWithChildren) => { @@ -16,7 +16,7 @@ export const URIAutocomplete = (props: React.PropsWithChildren) => { setShowOptions(options.filter((o) => o.value.indexOf(value) !== -1)); }, [options]); - const onChange = (value: string) => { + const onChange = _.debounce((value: string) => { setValue(value); const lastSlash = value.lastIndexOf(sep); @@ -24,28 +24,22 @@ export const URIAutocomplete = (props: React.PropsWithChildren) => { value = value.substring(0, lastSlash); } - if (timeout) { - clearTimeout(timeout); - } - - timeout = setTimeout(() => { - Backrest.PathAutocomplete({ value: value + sep }, { pathPrefix: "/api" }) - .then((res: StringList) => { - if (!res.values) { - return; - } - const vals = res.values.map((v) => { - return { - value: value + sep + v, - }; - }); - setOptions(vals); - }) - .catch((e) => { - console.log("Path autocomplete error: ", e); + backrestService.pathAutocomplete({ value: value + sep }) + .then((res: StringList) => { + if (!res.values) { + return; + } + const vals = res.values.map((v) => { + return { + value: value + sep + v, + }; }); - }, 100); - }; + setOptions(vals); + }) + .catch((e) => { + console.log("Path autocomplete error: ", e); + }); + }, 200); return ( ({ key: "config", - default: {}, + default: new Config(), }); export const fetchConfig = async (): Promise => { - return await Backrest.GetConfig({}, { pathPrefix: API_PREFIX }); + return await backrestService.getConfig({}); }; export const addRepo = async (repo: Repo): Promise => { - return await Backrest.AddRepo(repo, { - pathPrefix: API_PREFIX, - }); + return await backrestService.addRepo(repo); }; export const updateConfig = async (config: Config): Promise => { - return await Backrest.SetConfig(config, { - pathPrefix: API_PREFIX, - }); + return await backrestService.setConfig(config); }; diff --git a/webui/src/state/oplog.ts b/webui/src/state/oplog.ts index 45aacf0b..8a7df1e8 100644 --- a/webui/src/state/oplog.ts +++ b/webui/src/state/oplog.ts @@ -3,17 +3,12 @@ import { OperationEvent, OperationEventType, OperationStatus, -} from "../../gen/ts/v1/operations.pb"; -import { GetOperationsRequest, Backrest } from "../../gen/ts/v1/service.pb"; -import { API_PREFIX } from "../constants"; -import { BackupProgressEntry, ResticSnapshot } from "../../gen/ts/v1/restic.pb"; +} from "../../gen/ts/v1/operations_pb"; +import { GetOperationsRequest } from "../../gen/ts/v1/service_pb"; +import { BackupProgressEntry, ResticSnapshot } from "../../gen/ts/v1/restic_pb"; import _ from "lodash"; import { formatDuration, formatTime } from "../lib/formatting"; - -export type EOperation = Operation & { - parsedTime: number; - parsedDate: Date; -}; +import { backrestService } from "../api"; const subscribers: ((event: OperationEvent) => void)[] = []; @@ -22,16 +17,10 @@ const subscribers: ((event: OperationEvent) => void)[] = []; while (true) { let nextConnWaitUntil = new Date().getTime() + 5000; try { - await Backrest.GetOperationEvents( - {}, - (event: OperationEvent) => { - console.log("operation event", event); - subscribers.forEach((subscriber) => subscriber(event)); - }, - { - pathPrefix: API_PREFIX, - } - ); + for await (const event of backrestService.getOperationEvents({})) { + console.log("operation event", event); + subscribers.forEach((subscriber) => subscriber(event)); + } } catch (e: any) { console.error("operations stream died with exception: ", e); } @@ -43,11 +32,9 @@ const subscribers: ((event: OperationEvent) => void)[] = []; export const getOperations = async ( req: GetOperationsRequest -): Promise => { - const opList = await Backrest.GetOperations(req, { - pathPrefix: API_PREFIX, - }); - return (opList.operations || []).map(toEop); +): Promise => { + const opList = await backrestService.getOperations(req); + return (opList.operations || []); }; export const subscribeToOperations = ( @@ -66,18 +53,6 @@ export const unsubscribeFromOperations = ( } }; -export const toEop = (op: Operation): EOperation => { - const time = parseInt(op.unixTimeStartMs!); - const date = new Date(); - date.setTime(time); - - return { - ...op, - parsedTime: time, - parsedDate: date, - }; -}; - export enum DisplayType { UNKNOWN, BACKUP, @@ -110,22 +85,22 @@ export class BackupInfoCollector { event: OperationEventType, info: BackupInfo[] ) => void)[] = []; - private backupByOpId: { [key: string]: BackupInfo } = {}; - private backupBySnapshotId: { [key: string]: BackupInfo } = {}; + private backupByOpId: Map = new Map(); + private backupBySnapshotId: Map = new Map(); private createBackup(operations: Operation[]): BackupInfo { // deduplicate and sort operations. operations.sort((a, b) => { - return parseInt(b.unixTimeStartMs!) - parseInt(a.unixTimeStartMs!); + return Number(b.unixTimeStartMs - a.unixTimeStartMs); }); // use the lowest ID of all operations as the ID of the backup, this will be the first created operation. const id = operations.reduce((prev, curr) => { - return prev < curr.id! ? prev : curr.id!; + return prev < curr.id ? prev : curr.id; }, operations[0].id!); - const startTimeMs = parseInt(operations[0].unixTimeStartMs!); - const endTimeMs = parseInt(operations[operations.length - 1].unixTimeEndMs!); + const startTimeMs = Number(operations[0].unixTimeStartMs); + const endTimeMs = Number(operations[operations.length - 1].unixTimeEndMs!); const displayTime = new Date(startTimeMs); let displayType = DisplayType.SNAPSHOT; if (operations.length === 1) { @@ -144,16 +119,16 @@ export class BackupInfoCollector { let snapshotInfo = undefined; let forgotten = false; for (const op of operations) { - if (op.operationBackup) { - backupLastStatus = op.operationBackup.lastStatus; - } else if (op.operationIndexSnapshot) { - snapshotInfo = op.operationIndexSnapshot.snapshot; - forgotten = op.operationIndexSnapshot.forgot || false; + if (op.op.case === "operationBackup") { + backupLastStatus = op.op.value.lastStatus; + } else if (op.op.case === "operationIndexSnapshot") { + snapshotInfo = op.op.value.snapshot; + forgotten = op.op.value.forgot || false; } } return { - id, + id: id.toString(16), startTimeMs, endTimeMs, displayTime, @@ -170,9 +145,9 @@ export class BackupInfoCollector { private addHelper(op: Operation): BackupInfo { if (op.snapshotId) { - delete this.backupByOpId[op.id!]; + this.backupByOpId.delete(op.id); - const existing = this.backupBySnapshotId[op.snapshotId!]; + const existing = this.backupBySnapshotId.get(op.snapshotId) let operations: Operation[]; if (existing) { operations = [...existing.operations]; @@ -187,11 +162,11 @@ export class BackupInfoCollector { } const newInfo = this.createBackup(operations); - this.backupBySnapshotId[op.snapshotId!] = newInfo; + this.backupBySnapshotId.set(op.snapshotId, newInfo); return newInfo; } else { const newInfo = this.createBackup([op]); - this.backupByOpId[op.id!] = newInfo; + this.backupByOpId.set(op.id, newInfo); return newInfo; } } @@ -205,9 +180,9 @@ export class BackupInfoCollector { // removeOperaiton is not quite correct from a formal standpoint; but will look correct in the UI. public removeOperation(op: Operation) { if (op.snapshotId) { - delete this.backupBySnapshotId[op.snapshotId]; + this.backupBySnapshotId.delete(op.snapshotId); } else { - delete this.backupByOpId[op.id!]; + this.backupByOpId.delete(op.id); } this.listeners.forEach((l) => l(OperationEventType.EVENT_DELETED, this.getAll())); @@ -222,9 +197,10 @@ export class BackupInfoCollector { } public getAll(): BackupInfo[] { - const arr = []; - arr.push(...Object.values(this.backupByOpId)); - arr.push(...Object.values(this.backupBySnapshotId)); + const arr = [ + ...this.backupByOpId.values(), + ...this.backupBySnapshotId.values(), + ]; return arr.filter((b) => !b.forgotten && !shouldHideStatus(b.status)); } @@ -250,20 +226,19 @@ export const shouldHideStatus = (status: OperationStatus) => { }; export const getTypeForDisplay = (op: Operation) => { - if (op.operationForget) { - return DisplayType.FORGET; - } else if (op.operationPrune) { - return DisplayType.PRUNE; - } else if (op.operationBackup) { - return DisplayType.BACKUP; - } else if (op.operationIndexSnapshot) { - return DisplayType.SNAPSHOT; - } else if (op.operationPrune) { - return DisplayType.PRUNE; - } else if (op.operationRestore) { - return DisplayType.RESTORE; - } else { - return DisplayType.UNKNOWN; + switch (op.op.case) { + case "operationBackup": + return DisplayType.BACKUP; + case "operationIndexSnapshot": + return DisplayType.SNAPSHOT; + case "operationForget": + return DisplayType.FORGET; + case "operationPrune": + return DisplayType.PRUNE; + case "operationRestore": + return DisplayType.RESTORE; + default: + return DisplayType.UNKNOWN; } }; @@ -304,7 +279,7 @@ export const detailsForOperation = ( break; case OperationStatus.STATUS_INPROGRESS: state = "runnning"; - duration = new Date().getTime() - parseInt(op.unixTimeStartMs!); + duration = new Date().getTime() - Number(op.unixTimeStartMs); color = "blue"; break; case OperationStatus.STATUS_ERROR: @@ -330,25 +305,29 @@ export const detailsForOperation = ( switch (op.status) { case OperationStatus.STATUS_INPROGRESS: - duration = new Date().getTime() - parseInt(op.unixTimeStartMs!); - - if (op.operationBackup) { - const backup = op.operationBackup; - if (backup.lastStatus && backup.lastStatus.status) { - percentage = (backup.lastStatus.status.percentDone || 0) * 100; - } else if (backup.lastStatus && backup.lastStatus.summary) { - percentage = 100; + duration = new Date().getTime() - Number(op.unixTimeStartMs); + + if (op.op.case === "operationBackup") { + const backup = op.op.value; + switch (backup.lastStatus?.entry.case) { + case "status": + percentage = (backup.lastStatus!.entry.value.percentDone || 0) * 100; + break; + case "summary": + percentage = 100; + break; + default: + break; } - } else if (op.operationRestore) { - const restore = op.operationRestore; + } else if (op.op.case === "operationRestore") { + const restore = op.op.value; if (restore.status) { percentage = (restore.status.percentDone || 1) * 100; } } - break; default: - duration = parseInt(op.unixTimeEndMs!) - parseInt(op.unixTimeStartMs!); + duration = Number(op.unixTimeEndMs - op.unixTimeStartMs); break; } diff --git a/webui/src/views/AddPlanModal.tsx b/webui/src/views/AddPlanModal.tsx index 24ecb607..40523014 100644 --- a/webui/src/views/AddPlanModal.tsx +++ b/webui/src/views/AddPlanModal.tsx @@ -14,7 +14,7 @@ import { } from "antd"; import React, { useState } from "react"; import { useShowModal } from "../components/ModalManager"; -import { Plan, RetentionPolicy } from "../../gen/ts/v1/config.pb"; +import { Plan, RetentionPolicy } from "../../gen/ts/v1/config_pb"; import { useRecoilState } from "recoil"; import { configState, fetchConfig, updateConfig } from "../state/config"; import { nameRegex } from "../lib/patterns"; @@ -365,7 +365,7 @@ const RetentionPolicyView = ({ policy }: { policy?: RetentionPolicy }) => { CountBased, } - policy = policy || {}; + policy = policy || new RetentionPolicy(); const [policyType, setPolicyType] = useState( policy.keepLastN ? PolicyType.CountBased : PolicyType.TimeBased diff --git a/webui/src/views/AddRepoModal.tsx b/webui/src/views/AddRepoModal.tsx index 34ad78eb..825c81c5 100644 --- a/webui/src/views/AddRepoModal.tsx +++ b/webui/src/views/AddRepoModal.tsx @@ -11,11 +11,10 @@ import { } from "antd"; import React, { useState } from "react"; import { useShowModal } from "../components/ModalManager"; -import { Repo } from "../../gen/ts/v1/config.pb"; +import { Repo } from "../../gen/ts/v1/config_pb"; import { URIAutocomplete } from "../components/URIAutocomplete"; import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons"; import { useAlertApi } from "../components/Alerts"; -import { Backrest } from "../../gen/ts/v1/service.pb"; import { addRepo, configState, @@ -25,6 +24,7 @@ import { import { useRecoilState } from "recoil"; import { nameRegex } from "../lib/patterns"; import { validateForm } from "../lib/formutil"; +import { backrestService } from "../api"; export const AddRepoModal = ({ template, @@ -103,19 +103,14 @@ export const AddRepoModal = ({ alertsApi.error("Can't update repo, not found"); return; } - config.repos![idx] = { ...repo }; + config.repos![idx] = new Repo(repo); setConfig(await updateConfig(config)); showModal(null); alertsApi.success("Updated repo " + repo.uri); // Update the snapshots for the repo to confirm the config works. // TODO: this operation is only used here, find a different RPC for this purpose. - await Backrest.ListSnapshots( - { - repoId: repo.id, - }, - { pathPrefix: "/api" } - ); + await backrestService.listSnapshots({ repoId: repo.id }); } else { // We are in the create repo flow, create the new repo via the service setConfig(await addRepo(repo)); @@ -320,7 +315,7 @@ export const AddRepoModal = ({ form.validateFields()} - style={{ width: "60%" }} + style={{ width: "90%" }} /> add()} - style={{ width: "60%" }} + style={{ width: "90%" }} icon={} > Set Environment Variable @@ -417,6 +412,8 @@ export const AddRepoModal = ({ const expectedEnvVars: { [scheme: string]: string[] } = { s3: ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"], b2: ["B2_ACCOUNT_ID", "B2_ACCOUNT_KEY"], + azure: ["AZURE_ACCOUNT_NAME", "AZURE_ACCOUNT_KEY"], + gs: ["GOOGLE_APPLICATION_CREDENTIALS", "GOOGLE_PROJECT_ID"], }; const envVarSetValidator = (uri: string | undefined, envVars: string[]) => { diff --git a/webui/src/views/App.tsx b/webui/src/views/App.tsx index 378e83b6..e9de6923 100644 --- a/webui/src/views/App.tsx +++ b/webui/src/views/App.tsx @@ -10,7 +10,7 @@ import type { MenuProps } from "antd"; import { Button, Layout, Menu, Spin, theme } from "antd"; import { configState, fetchConfig } from "../state/config"; import { useRecoilState } from "recoil"; -import { Config } from "../../gen/ts/v1/config.pb"; +import { Config } from "../../gen/ts/v1/config_pb"; import { useAlertApi } from "../components/Alerts"; import { useShowModal } from "../components/ModalManager"; import { MainContentArea, useSetContent } from "./MainContentArea"; diff --git a/webui/src/views/PlanView.tsx b/webui/src/views/PlanView.tsx index bae2e2cd..b508c173 100644 --- a/webui/src/views/PlanView.tsx +++ b/webui/src/views/PlanView.tsx @@ -1,13 +1,14 @@ import React, { useEffect, useState } from "react"; -import { Plan } from "../../gen/ts/v1/config.pb"; +import { Plan } from "../../gen/ts/v1/config_pb"; import { Button, Flex, Tabs, Tooltip, Typography } from "antd"; import { useRecoilValue } from "recoil"; import { configState } from "../state/config"; import { useAlertApi } from "../components/Alerts"; -import { Backrest } from "../../gen/ts/v1/service.pb"; import { OperationList } from "../components/OperationList"; import { OperationTree } from "../components/OperationTree"; import { MAX_OPERATION_HISTORY } from "../constants"; +import { backrestService } from "../api"; +import { GetOperationsRequest } from "../../gen/ts/v1/service_pb"; export const PlanView = ({ plan }: React.PropsWithChildren<{ plan: Plan }>) => { const alertsApi = useAlertApi()!; @@ -22,7 +23,7 @@ export const PlanView = ({ plan }: React.PropsWithChildren<{ plan: Plan }>) => { const handleBackupNow = async () => { try { - Backrest.Backup({ value: plan.id }, { pathPrefix: "/api" }); + backrestService.backup({ value: plan.id }); alertsApi.success("Backup scheduled."); } catch (e: any) { alertsApi.error("Failed to schedule backup: " + e.message); @@ -31,7 +32,7 @@ export const PlanView = ({ plan }: React.PropsWithChildren<{ plan: Plan }>) => { const handlePruneNow = () => { try { - Backrest.Prune({ value: plan.id }, { pathPrefix: "/api" }); + backrestService.prune({ value: plan.id }); alertsApi.success("Prune scheduled."); } catch (e: any) { alertsApi.error("Failed to schedule prune: " + e.message); @@ -41,7 +42,7 @@ export const PlanView = ({ plan }: React.PropsWithChildren<{ plan: Plan }>) => { const handleUnlockNow = () => { try { alertsApi.info("Unlocking repo..."); - Backrest.Unlock({ value: plan.repo! }, { pathPrefix: "/api" }); + backrestService.unlock({ value: plan.repo! }); alertsApi.success("Repo unlocked."); } catch (e: any) { alertsApi.error("Failed to unlock repo: " + e.message); @@ -51,7 +52,7 @@ export const PlanView = ({ plan }: React.PropsWithChildren<{ plan: Plan }>) => { const handleClearErrorHistory = () => { try { alertsApi.info("Clearing error history..."); - Backrest.ClearHistory({ planId: plan.id, onlyFailed: true }, { pathPrefix: "/api" }); + backrestService.clearHistory({ planId: plan.id, onlyFailed: true }); alertsApi.success("Error history cleared."); } catch (e: any) { alertsApi.error("Failed to clear error history: " + e.message); @@ -94,7 +95,7 @@ export const PlanView = ({ plan }: React.PropsWithChildren<{ plan: Plan }>) => { children: ( <> ), @@ -106,7 +107,7 @@ export const PlanView = ({ plan }: React.PropsWithChildren<{ plan: Plan }>) => { <>

Backup Action History

), diff --git a/webui/src/views/RepoView.tsx b/webui/src/views/RepoView.tsx index fd249b32..31daf159 100644 --- a/webui/src/views/RepoView.tsx +++ b/webui/src/views/RepoView.tsx @@ -1,13 +1,13 @@ -import React, { useEffect, useState } from "react"; -import { Repo } from "../../gen/ts/v1/config.pb"; -import { Button, Flex, Tabs, Tooltip, Typography } from "antd"; +import React from "react"; +import { Repo } from "../../gen/ts/v1/config_pb"; +import { Flex, Tabs, Typography } from "antd"; import { useRecoilValue } from "recoil"; import { configState } from "../state/config"; import { useAlertApi } from "../components/Alerts"; -import { Backrest } from "../../gen/ts/v1/service.pb"; import { OperationList } from "../components/OperationList"; import { OperationTree } from "../components/OperationTree"; import { MAX_OPERATION_HISTORY } from "../constants"; +import { GetOperationsRequest } from "../../gen/ts/v1/service_pb"; export const RepoView = ({ repo }: React.PropsWithChildren<{ repo: Repo }>) => { const alertsApi = useAlertApi()!; @@ -36,7 +36,7 @@ export const RepoView = ({ repo }: React.PropsWithChildren<{ repo: Repo }>) => { children: ( <> ), @@ -48,7 +48,7 @@ export const RepoView = ({ repo }: React.PropsWithChildren<{ repo: Repo }>) => { <>

Backup Action History